From: Nick Porter Date: Wed, 17 Apr 2024 14:32:42 +0000 (+0100) Subject: Update main SQL queries to reflect new structure X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=756424e83a86838b3b5653b7bd0f3047fa36c7fd;p=thirdparty%2Ffreeradius-server.git Update main SQL queries to reflect new structure Accounting queries go under accounting { { query = "..." } } Post-Auth is now send { { query = "..." } } --- diff --git a/raddb/mods-config/sql/main/cassandra/queries.conf b/raddb/mods-config/sql/main/cassandra/queries.conf index f1ecf277c9..810be8a0e8 100644 --- a/raddb/mods-config/sql/main/cassandra/queries.conf +++ b/raddb/mods-config/sql/main/cassandra/queries.conf @@ -108,9 +108,16 @@ authorize_group_reply_query = "\ # Accounting and Post-Auth Queries ####################################################################### # These queries insert/update accounting and authentication records. -# The query to use is determined by the value of 'reference'. -# This value is used as a configuration path and should resolve to exactly -# one query. +# The query to use is determined by the name of the section the module +# is called from. +# +# e.g. when called from `accouting Start`, the contents of +# +# accounting { +# start {} +# } +# +# will be read, and the "query" entry found will be used. # # Unlike other SQL drivers, the rlm_cassandra driver will always # indicate a single row was updated. This is because the updates aren't @@ -120,211 +127,207 @@ authorize_group_reply_query = "\ # as INSERTS are really UPSERTS so we can work around it. ####################################################################### accounting { - reference = "%tolower(type.%{Acct-Status-Type}.query)" - # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/accounting.sql - type { - # - # Because cassandra doesn't allow secondary indexes to be used in update statements - # applying acct on/off packets must be done outside of the server, by a script that - # first performs a SELECT to identify candidate rows, then closes out the sessions. - # - accounting-on { - query = "\ - INSERT INTO radnasreboot (nasipaddress, timestamp) \ - VALUES ('%{NAS-IP-Address}', ${....event_timestamp});" - } + # + # Because cassandra doesn't allow secondary indexes to be used in update statements + # applying acct on/off packets must be done outside of the server, by a script that + # first performs a SELECT to identify candidate rows, then closes out the sessions. + # + accounting-on { + query = "\ + INSERT INTO radnasreboot (nasipaddress, timestamp) \ + VALUES ('%{NAS-IP-Address}', ${...event_timestamp});" + } - accounting-off { - query = "${..accounting-on.query}" - } + accounting-off { + query = "${..accounting-on.query}" + } - start { - # - # Insert a new record into the sessions table - # - query = "\ - INSERT INTO ${....acct_table1} ( \ - acctuniqueid, \ - acctsessionid, \ - username, \ - realm, \ - nasipaddress, \ - nasportid, \ - nasporttype, \ - acctstarttime, \ - acctupdatetime, \ - acctstoptime, \ - acctauthentic, \ - connectinfo_start, \ - acctinputoctets, \ - acctoutputoctets, \ - calledstationid, \ - callingstationid, \ - servicetype, \ - framedprotocol, \ - framedipaddress, \ - framedipv6address, \ - framedipv6prefix, \ - framedinterfaceid, \ - delegatedipv6prefix, \ - class - ) VALUES ( \ - '%{Acct-Unique-Session-Id}', \ - '%{Acct-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-Id || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - null, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - 0, \ - 0, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}' - );" - } + start { + # + # Insert a new record into the sessions table + # + query = "\ + INSERT INTO ${...acct_table1} ( \ + acctuniqueid, \ + acctsessionid, \ + username, \ + realm, \ + nasipaddress, \ + nasportid, \ + nasporttype, \ + acctstarttime, \ + acctupdatetime, \ + acctstoptime, \ + acctauthentic, \ + connectinfo_start, \ + acctinputoctets, \ + acctoutputoctets, \ + calledstationid, \ + callingstationid, \ + servicetype, \ + framedprotocol, \ + framedipaddress, \ + framedipv6address, \ + framedipv6prefix, \ + framedinterfaceid, \ + delegatedipv6prefix, \ + class + ) VALUES ( \ + '%{Acct-Unique-Session-Id}', \ + '%{Acct-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-Id || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + null, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + 0, \ + 0, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}' + );" + } - interim-update { - query = "\ - BEGIN BATCH \ - INSERT INTO ${....acct_table1} ( \ - acctuniqueid, \ - acctstarttime \ - ) VALUES ( \ - '%{Acct-Unique-Session-Id}', \ - %{(${....event_timestamp_epoch} - &Acct-Session-Time) * 1000} \ - ) IF NOT EXISTS; \ - INSERT INTO ${....acct_table1} ( \ - acctuniqueid, \ - acctsessionid, \ - username, \ - realm, \ - nasipaddress, \ - nasportid, \ - nasporttype, \ - acctupdatetime, \ - acctstoptime, \ - acctauthentic, \ - connectinfo_start, \ - acctinputoctets, \ - acctoutputoctets, \ - calledstationid, \ - callingstationid, \ - servicetype, \ - framedprotocol, \ - framedipaddress, \ - framedipv6address, \ - framedipv6prefix, \ - framedinterfaceid, \ - delegatedipv6prefix, \ - class \ - ) VALUES ( \ - '%{Acct-Unique-Session-Id}', \ - '%{Acct-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-Id || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - null, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}' \ - ); \ - APPLY BATCH;" - } + interim-update { + query = "\ + BEGIN BATCH \ + INSERT INTO ${...acct_table1} ( \ + acctuniqueid, \ + acctstarttime \ + ) VALUES ( \ + '%{Acct-Unique-Session-Id}', \ + %{(${...event_timestamp_epoch} - &Acct-Session-Time) * 1000} \ + ) IF NOT EXISTS; \ + INSERT INTO ${...acct_table1} ( \ + acctuniqueid, \ + acctsessionid, \ + username, \ + realm, \ + nasipaddress, \ + nasportid, \ + nasporttype, \ + acctupdatetime, \ + acctstoptime, \ + acctauthentic, \ + connectinfo_start, \ + acctinputoctets, \ + acctoutputoctets, \ + calledstationid, \ + callingstationid, \ + servicetype, \ + framedprotocol, \ + framedipaddress, \ + framedipv6address, \ + framedipv6prefix, \ + framedinterfaceid, \ + delegatedipv6prefix, \ + class \ + ) VALUES ( \ + '%{Acct-Unique-Session-Id}', \ + '%{Acct-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-Id || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + null, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}' \ + ); \ + APPLY BATCH;" + } - stop { - query = "\ - BEGIN BATCH \ - INSERT INTO ${....acct_table1} ( \ - acctuniqueid, \ - acctstarttime \ - ) VALUES ( \ - '%{Acct-Unique-Session-Id}', \ - %{(${....event_timestamp_epoch} - &Acct-Session-Time) * 1000} \ - ) IF NOT EXISTS; \ - INSERT INTO ${....acct_table1} ( \ - acctuniqueid, \ - acctsessionid, \ - username, \ - realm, \ - nasipaddress, \ - nasportid, \ - nasporttype, \ - acctupdatetime, \ - acctstoptime, \ - acctauthentic, \ - connectinfo_stop, \ - acctinputoctets, \ - acctoutputoctets, \ - calledstationid, \ - callingstationid, \ - servicetype, \ - framedprotocol, \ - framedipaddress, \ - framedipv6address, \ - framedipv6prefix, \ - framedinterfaceid, \ - delegatedipv6prefix, \ - acctterminatecause, \ - class \ - ) VALUES ( \ - '%{Acct-Unique-Session-Id}', \ - '%{Acct-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-Id || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Acct-Terminate-Cause}', \ - '%{Class}' \ - ); \ - APPLY BATCH;" - } + stop { + query = "\ + BEGIN BATCH \ + INSERT INTO ${...acct_table1} ( \ + acctuniqueid, \ + acctstarttime \ + ) VALUES ( \ + '%{Acct-Unique-Session-Id}', \ + %{(${...event_timestamp_epoch} - &Acct-Session-Time) * 1000} \ + ) IF NOT EXISTS; \ + INSERT INTO ${...acct_table1} ( \ + acctuniqueid, \ + acctsessionid, \ + username, \ + realm, \ + nasipaddress, \ + nasportid, \ + nasporttype, \ + acctupdatetime, \ + acctstoptime, \ + acctauthentic, \ + connectinfo_stop, \ + acctinputoctets, \ + acctoutputoctets, \ + calledstationid, \ + callingstationid, \ + servicetype, \ + framedprotocol, \ + framedipaddress, \ + framedipv6address, \ + framedipv6prefix, \ + framedinterfaceid, \ + delegatedipv6prefix, \ + acctterminatecause, \ + class \ + ) VALUES ( \ + '%{Acct-Unique-Session-Id}', \ + '%{Acct-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-Id || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Acct-Terminate-Cause}', \ + '%{Class}' \ + ); \ + APPLY BATCH;" } } @@ -332,21 +335,27 @@ accounting { ####################################################################### # Authentication Logging Queries ####################################################################### -# postauth_query - Insert some info after authentication +# send queries - Insert some info after authentication ####################################################################### -post-auth { +send { # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/post-auth.sql - query = "\ - INSERT INTO ${..postauth_table} \ - (username, pass, reply, authdate, class) \ - VALUES ( \ - '%{SQL-User-Name}', \ - '%{&User-Password || &Chap-Password}', \ - '%{reply.Packet-Type}', \ - '%{%l * 1000 + %M / 1000}', \ - '%{reply.Class}')" + access-accept { + query = "\ + INSERT INTO ${...postauth_table} \ + (username, pass, reply, authdate, class) \ + VALUES ( \ + '%{SQL-User-Name}', \ + '%{&User-Password || &Chap-Password}', \ + '%{reply.Packet-Type}', \ + '%{%l * 1000 + %M / 1000}', \ + '%{reply.Class}')" + } + + access-reject { + query = "${..access-accept.query}" + } } diff --git a/raddb/mods-config/sql/main/mssql/queries.conf b/raddb/mods-config/sql/main/mssql/queries.conf index 4e66e4a25f..c3d2badf26 100644 --- a/raddb/mods-config/sql/main/mssql/queries.conf +++ b/raddb/mods-config/sql/main/mssql/queries.conf @@ -102,284 +102,290 @@ group_membership_query = "\ ORDER BY priority" ####################################################################### -# Accounting and Post-Auth Queries +# Accounting and Send Queries ####################################################################### # These queries insert/update accounting and authentication records. -# The query to use is determined by the value of 'reference'. -# This value is used as a configuration path and should resolve to one -# or more 'query's. If reference points to multiple queries, and a query -# fails, the next query is executed. +# The query to use is determined by the name of the section the module +# is called from. # -# Behaviour is identical to the old 1.x/2.x module, except we can now -# fail between N queries, and query selection can be based on any -# combination of attributes, or custom 'Acct-Status-Type' values. +# e.g. when called from `accouting Start`, the contents of +# +# accounting { +# start {} +# } +# +# will be read, and any "query" entries will be run in sequence +# until one returns a positive number of modified rows. ####################################################################### accounting { - reference = "%tolower(type.%{Acct-Status-Type}.query)" - # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/accounting.sql - type { - accounting-on { - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctStopTime=${....event_timestamp}, \ - AcctSessionTime=${....event_timestamp_epoch} - \ - DATEDIFF(SS, '1970-01-01', AcctStartTime), \ - AcctTerminateCause='%{&Acct-Terminate-Cause || \'NAS-Reboot\'}', \ - AcctStopDelay = %{&Acct-Delay-Time || 0} \ - WHERE AcctStopTime = 0 \ - AND NASIPAddress = '%{NAS-IP-Address}' \ - AND AcctStartTime <= ${....event_timestamp}" + accounting-on { + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctStopTime=${...event_timestamp}, \ + AcctSessionTime=${...event_timestamp_epoch} - \ + DATEDIFF(SS, '1970-01-01', AcctStartTime), \ + AcctTerminateCause='%{&Acct-Terminate-Cause || 'NAS-Reboot'}', \ + AcctStopDelay = %{&Acct-Delay-Time || 0} \ + WHERE AcctStopTime = 0 \ + AND NASIPAddress = '%{NAS-IP-Address}' \ + AND AcctStartTime <= ${...event_timestamp}" - # - # If there are no open user sessions, then the previous query - # will return "no rows updated". The server will then fall through - # to the next query, which is just "yes, that's fine". - # - query = "SELECT true" - } + # + # If there are no open user sessions, then the previous query + # will return "no rows updated". The server will then fall through + # to the next query, which is just "yes, that's fine". + # + query = "SELECT true" + } - accounting-off { - query = "${..accounting-on.query}" + accounting-off { + query = "${..accounting-on.query}" - query = "SELECT true" - } + query = "SELECT true" + } - start { - query = "\ - INSERT INTO ${....acct_table1} ( \ - AcctSessionId, \ - AcctUniqueId, \ - UserName, \ - Realm, \ - NASIPAddress, \ - NASPortId, \ - NASPortType, \ - AcctStartTime, \ - AcctSessionTime, \ - AcctAuthentic, \ - ConnectInfo_start, \ - ConnectInfo_stop, \ - AcctInputOctets, \ - AcctOutputOctets, \ - CalledStationId, \ - CallingStationId, \ - AcctTerminateCause, \ - ServiceType, \ - FramedProtocol, \ - FramedIPAddress, \ - FramedIPv6Address, \ - FramedIPv6Prefix, \ - FramedInterfaceId, \ - DelegatedIPv6Prefix, \ - AcctStartDelay, \ - AcctStopDelay, \ - Class) \ - VALUES(\ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - '0', \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - '', \ - '0', \ - '0', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Acct-Delay-Time}', \ - '0', \ - '%{Class}')" + start { + query = "\ + INSERT INTO ${...acct_table1} ( \ + AcctSessionId, \ + AcctUniqueId, \ + UserName, \ + Realm, \ + NASIPAddress, \ + NASPortId, \ + NASPortType, \ + AcctStartTime, \ + AcctSessionTime, \ + AcctAuthentic, \ + ConnectInfo_start, \ + ConnectInfo_stop, \ + AcctInputOctets, \ + AcctOutputOctets, \ + CalledStationId, \ + CallingStationId, \ + AcctTerminateCause, \ + ServiceType, \ + FramedProtocol, \ + FramedIPAddress, \ + FramedIPv6Address, \ + FramedIPv6Prefix, \ + FramedInterfaceId, \ + DelegatedIPv6Prefix, \ + AcctStartDelay, \ + AcctStopDelay, \ + Class) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + '0', \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '0', \ + '0', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Acct-Delay-Time}', \ + '0', \ + '%{Class}')" - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctStartTime = ${....event_timestamp}, \ - AcctStartDelay = '%{&Acct-Delay-Time || 0}', \ - ConnectInfo_start = '%{Connect-Info}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ - AND AcctStopTime = 0" - } + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctStartTime = ${...event_timestamp}, \ + AcctStartDelay = '%{&Acct-Delay-Time || 0}', \ + ConnectInfo_start = '%{Connect-Info}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ + AND AcctStopTime = 0" + } - interim-update { - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctInterval = DATEDIFF(second, CASE WHEN AcctUpdateTime > 0 THEN AcctUpdateTime ELSE AcctStartTime END, ${....event_timestamp}), \ - AcctUpdateTime = ${....event_timestamp}, \ - AcctSessionTime = '%{Acct-Session-Time}', \ - AcctInputOctets = convert(bigint, '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}'), \ - AcctOutputOctets = convert(bigint, '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}'), \ - FramedIPAddress = '%{Framed-IP-Address}', \ - FramedIPv6Address = '%{Framed-IPv6-Address}', \ - FramedIPv6Prefix = '%{Framed-IPv6-Prefix}', \ - FramedInterfaceId = '%{Framed-Interface-Id}', \ - DelegatedIPv6Prefix = '%{Delegated-IPv6-Prefix}', \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ - AND AcctStopTime = 0" + interim-update { + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctInterval = DATEDIFF(second, CASE WHEN AcctUpdateTime > 0 THEN AcctUpdateTime ELSE AcctStartTime END, ${...event_timestamp}), \ + AcctUpdateTime = ${...event_timestamp}, \ + AcctSessionTime = '%{Acct-Session-Time}', \ + AcctInputOctets = convert(bigint, '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}'), \ + AcctOutputOctets = convert(bigint, '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}'), \ + FramedIPAddress = '%{Framed-IP-Address}', \ + FramedIPv6Address = '%{Framed-IPv6-Address}', \ + FramedIPv6Prefix = '%{Framed-IPv6-Prefix}', \ + FramedInterfaceId = '%{Framed-Interface-Id}', \ + DelegatedIPv6Prefix = '%{Delegated-IPv6-Prefix}', \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ + AND AcctStopTime = 0" - query = "\ - INSERT INTO ${....acct_table1} ( \ - AcctSessionId, \ - AcctUniqueId, \ - UserName, \ - Realm, \ - NASIPAddress, \ - NASPortId, \ - NASPortType, \ - AcctStartTime, \ - AcctUpdateTime, \ - AcctSessionTime, \ - AcctAuthentic, \ - ConnectInfo_start, \ - AcctInputOctets, \ - AcctOutputOctets, \ - CalledStationId, \ - CallingStationId, \ - ServiceType, \ - FramedProtocol, \ - FramedIPAddress, \ - FramedIPv6Address, \ - FramedIPv6Prefix, \ - FramedInterfaceId, \ - DelegatedIPv6Prefix, \ - AcctStartDelay, \ - Class) \ - VALUES(\ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - '%{Acct-Session-Time}', \ - '%{Acct-Authentic}', \ - '', \ - '%{Acct-Input-Octets}', \ - '%{Acct-Output-Octets}', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '0' \ - '%{Class}')" - } + query = "\ + INSERT INTO ${...acct_table1} ( \ + AcctSessionId, \ + AcctUniqueId, \ + UserName, \ + Realm, \ + NASIPAddress, \ + NASPortId, \ + NASPortType, \ + AcctStartTime, \ + AcctUpdateTime, \ + AcctSessionTime, \ + AcctAuthentic, \ + ConnectInfo_start, \ + AcctInputOctets, \ + AcctOutputOctets, \ + CalledStationId, \ + CallingStationId, \ + ServiceType, \ + FramedProtocol, \ + FramedIPAddress, \ + FramedIPv6Address, \ + FramedIPv6Prefix, \ + FramedInterfaceId, \ + DelegatedIPv6Prefix, \ + AcctStartDelay, \ + Class) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + '%{Acct-Session-Time}', \ + '%{Acct-Authentic}', \ + '', \ + '%{Acct-Input-Octets}', \ + '%{Acct-Output-Octets}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '0' \ + '%{Class}')" + } - stop { - query = "\ - UPDATE ${....acct_table2} \ - SET \ - AcctStopTime = ${....event_timestamp}, \ - AcctSessionTime = '%{Acct-Session-Time}', \ - AcctInputOctets = convert(bigint, '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}'), \ - AcctOutputOctets = convert(bigint, '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}'), \ - AcctTerminateCause = '%{Acct-Terminate-Cause}', \ - AcctStopDelay = '%{&Acct-Delay-Time || 0}', \ - ConnectInfo_stop = '%{Connect-Info}', \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ - AND AcctStopTime = 0" + stop { + query = "\ + UPDATE ${...acct_table2} \ + SET \ + AcctStopTime = ${...event_timestamp}, \ + AcctSessionTime = '%{Acct-Session-Time}', \ + AcctInputOctets = convert(bigint, '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}'), \ + AcctOutputOctets = convert(bigint, '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}'), \ + AcctTerminateCause = '%{Acct-Terminate-Cause}', \ + AcctStopDelay = '%{&Acct-Delay-Time || 0}', \ + ConnectInfo_stop = '%{Connect-Info}', \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ + AND AcctStopTime = 0" - query = "\ - INSERT into ${....acct_table2} (\ - AcctSessionId, \ - AcctUniqueId, \ - UserName, \ - Realm, \ - NASIPAddress, \ - NASPortId, \ - NASPortType, \ - AcctStopTime, \ - AcctSessionTime, \ - AcctAuthentic, \ - ConnectInfo_start, \ - ConnectInfo_stop, \ - AcctInputOctets, \ - AcctOutputOctets, \ - CalledStationId, \ - CallingStationId, \ - AcctTerminateCause, \ - ServiceType, \ - FramedProtocol, \ - FramedIPAddress, \ - FramedIPv6Address, \ - FramedIPv6Prefix, \ - FramedInterfaceId, \ - DelegatedIPv6Prefix, \ - AcctStartDelay, \ - AcctStopDelay, \ - Class) \ - VALUES(\ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - '%{Acct-Session-Time}', \ - '%{Acct-Authentic}', \ - '', \ - '%{Connect-Info}', \ - NULL, \ - convert(bigint, '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}'), \ - convert(bigint, '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}'), \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Acct-Terminate-Cause}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '0', \ - '%{&Acct-Delay-Time || 0}', \ - '%{Class}')" - } + query = "\ + INSERT into ${...acct_table2} (\ + AcctSessionId, \ + AcctUniqueId, \ + UserName, \ + Realm, \ + NASIPAddress, \ + NASPortId, \ + NASPortType, \ + AcctStopTime, \ + AcctSessionTime, \ + AcctAuthentic, \ + ConnectInfo_start, \ + ConnectInfo_stop, \ + AcctInputOctets, \ + AcctOutputOctets, \ + CalledStationId, \ + CallingStationId, \ + AcctTerminateCause, \ + ServiceType, \ + FramedProtocol, \ + FramedIPAddress, \ + FramedIPv6Address, \ + FramedIPv6Prefix, \ + FramedInterfaceId, \ + DelegatedIPv6Prefix, \ + AcctStartDelay, \ + AcctStopDelay, \ + Class) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + '%{Acct-Session-Time}', \ + '%{Acct-Authentic}', \ + '', \ + '%{Connect-Info}', \ + NULL, \ + convert(bigint, '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}'), \ + convert(bigint, '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}'), \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Acct-Terminate-Cause}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '0', \ + '%{&Acct-Delay-Time || 0}', \ + '%{Class}')" } } -post-auth { + +send { # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/post-auth.sql - query = "\ - INSERT INTO ${..postauth_table} \ - (userName, pass, reply, authdate, class) \ - VALUES(\ - '%{User-Name}', \ - '%{&User-Password || CHAP-PASSWORD}', \ - '%{reply.Packet-Type}', \ - '%S.%{%M / 1000}', \ - '%{reply.Class}')" + access-accept { + query = "\ + INSERT INTO ${...postauth_table} \ + (userName, pass, reply, authdate, class) \ + VALUES(\ + '%{User-Name}', \ + '%{&User-Password || CHAP-PASSWORD}', \ + '%{reply.Packet-Type}', \ + '%S.%{%M / 1000}', \ + '%{reply.Class}')" + } + + access-reject { + query = "${..access-accept.query}" + } } diff --git a/raddb/mods-config/sql/main/mysql/queries.conf b/raddb/mods-config/sql/main/mysql/queries.conf index 159eda9d5a..f366920ae4 100644 --- a/raddb/mods-config/sql/main/mysql/queries.conf +++ b/raddb/mods-config/sql/main/mysql/queries.conf @@ -134,18 +134,19 @@ authorize_group_reply_query = "\ # Accounting and Post-Auth Queries ####################################################################### # These queries insert/update accounting and authentication records. -# The query to use is determined by the value of 'reference'. -# This value is used as a configuration path and should resolve to one -# or more 'query's. If reference points to multiple queries, and a query -# fails, the next query is executed. +# The query to use is determined by the name of the section the module +# is called from. # -# Behaviour is identical to the old 1.x/2.x module, except we can now -# fail between N queries, and query selection can be based on any -# combination of attributes, or custom 'Acct-Status-Type' values. +# e.g. when called from `accouting Start`, the contents of +# +# accounting { +# start {} +# } +# +# will be read, and any "query" entries will be run in sequence +# until one returns a positive number of modified rows. ####################################################################### accounting { - reference = "%tolower(type.%{Acct-Status-Type}.query)" - # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/accounting.sql @@ -161,231 +162,229 @@ accounting { framedipaddress, framedipv6address, framedipv6prefix, \ framedinterfaceid, delegatedipv6prefix, class" - type { - accounting-on { - - # - # "Bulk update" Accounting-On/Off strategy. - # - # Immediately terminate all sessions associated with a - # given NAS. - # - # Note: If a large number of sessions require closing - # then the bulk update may be take a long time to run - # and lock an excessive number of rows. See the - # strategy below for an alternative approach that does - # not touch the radacct session data. - # - query = "\ - UPDATE ${....acct_table1} \ - SET \ - acctstoptime = ${....event_timestamp}, \ - acctsessiontime = '${....event_timestamp_epoch}' \ - - UNIX_TIMESTAMP(acctstarttime), \ - acctterminatecause = '%{&Acct-Terminate-Cause || \'NAS-Reboot\'}' \ - WHERE acctstoptime IS NULL \ - AND nasipaddress = '%{NAS-IP-Address}' \ - AND acctstarttime <= ${....event_timestamp}" - - # - # "Lightweight" Accounting-On/Off strategy. - # - # Record the reload time of the NAS and let the - # administrator actually close the sessions in radacct - # out-of-band, if desired. - # - # Implementation advice, together with a stored - # procedure for closing sessions and a view showing - # the effective stop time of each session is provided - # in process-radacct.sql. - # - # To enable this strategy, just change the previous - # query to "-query", and this one to "query". The - # previous one will be ignored, and this one will be - # enabled. - # - -query = "\ - INSERT INTO nasreload \ - SET \ - nasipaddress = '%{NAS-IP-Address}', \ - reloadtime = ${....event_timestamp} \ - ON DUPLICATE KEY UPDATE reloadtime = ${....event_timestamp}" - - # If there are no open user sessions, then the previous query - # will return "no rows updated". The server will then fall through - # to the next query, which is just "yes, that's fine". - # - query = "SELECT true" - - } - - accounting-off { - query = "${..accounting-on.query}" - - query = "SELECT true" - } - - start { - # - # Insert a new record into the sessions table - # - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES \ - ('%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - NULL, \ - '0', \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - '', \ - '0', \ - '0', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}')" - - # - # Key constraints prevented us from inserting a new session, - # use the alternate query to update an existing session. - # - query = "\ - UPDATE ${....acct_table1} SET \ - acctstarttime = ${....event_timestamp}, \ - acctupdatetime = ${....event_timestamp}, \ - connectinfo_start = '%{Connect-Info}', \ - class = '%{Class}' \ - WHERE acctuniqueid = '%{Acct-Unique-Session-Id}'" - } - - interim-update { - # - # Update an existing session and calculate the interval - # between the last data we received for the session and this - # update. This can be used to find stale sessions. - # - query = "\ - UPDATE ${....acct_table1} \ - SET \ - acctupdatetime = (@acctupdatetime_old:=acctupdatetime), \ - acctupdatetime = ${....event_timestamp}, \ - acctinterval = ${....event_timestamp_epoch} - \ - UNIX_TIMESTAMP(@acctupdatetime_old), \ - framedipaddress = '%{Framed-IP-Address}', \ - framedipv6address = '%{Framed-IPv6-Address}', \ - framedipv6prefix = '%{Framed-IPv6-Prefix}', \ - framedinterfaceid = '%{Framed-Interface-Id}', \ - delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ - acctsessiontime = %{&Acct-Session-Time || \'NULL\'}, \ - acctinputoctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - acctoutputoctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - class = '%{Class}' \ - WHERE acctuniqueid = '%{Acct-Unique-Session-Id}'" - - # - # The update condition matched no existing sessions. Use - # the values provided in the update to create a new session. - # - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES \ - ('%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - FROM_UNIXTIME(${....event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ - ${....event_timestamp}, \ - NULL, \ - %{&Acct-Session-Time || \'NULL\'}, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - '', \ - '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ - '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}')" - } - - stop { - # - # Session has terminated, update the stop time and statistics. - # - query = "\ - UPDATE ${....acct_table2} SET \ - acctstoptime = ${....event_timestamp}, \ - acctsessiontime = %{&Acct-Session-Time || \'NULL\'}, \ - acctinputoctets = '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ - acctoutputoctets = '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ - acctterminatecause = '%{Acct-Terminate-Cause}', \ - connectinfo_stop = '%{Connect-Info}', \ - class = '%{Class}' \ - WHERE acctuniqueid = '%{Acct-Unique-Session-Id}'" - - # - # The update condition matched no existing sessions. Use - # the values provided in the update to create a new session. - # - query = "\ - INSERT INTO ${....acct_table2} \ - (${...column_list}) \ - VALUES \ - ('%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - FROM_UNIXTIME(${....event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - %{&Acct-Session-Time || \'NULL\'}, \ - '%{Acct-Authentic}', \ - '', \ - '%{Connect-Info}', \ - '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ - '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Acct-Terminate-Cause}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}')" - } + accounting-on { + + # + # "Bulk update" Accounting-On/Off strategy. + # + # Immediately terminate all sessions associated with a + # given NAS. + # + # Note: If a large number of sessions require closing + # then the bulk update may be take a long time to run + # and lock an excessive number of rows. See the + # strategy below for an alternative approach that does + # not touch the radacct session data. + # + query = "\ + UPDATE ${...acct_table1} \ + SET \ + acctstoptime = ${...event_timestamp}, \ + acctsessiontime = '${...event_timestamp_epoch}' \ + - UNIX_TIMESTAMP(acctstarttime), \ + acctterminatecause = '%{&Acct-Terminate-Cause || \'NAS-Reboot\'}' \ + WHERE acctstoptime IS NULL \ + AND nasipaddress = '%{NAS-IP-Address}' \ + AND acctstarttime <= ${...event_timestamp}" + + # + # "Lightweight" Accounting-On/Off strategy. + # + # Record the reload time of the NAS and let the + # administrator actually close the sessions in radacct + # out-of-band, if desired. + # + # Implementation advice, together with a stored + # procedure for closing sessions and a view showing + # the effective stop time of each session is provided + # in process-radacct.sql. + # + # To enable this strategy, just change the previous + # query to "-query", and this one to "query". The + # previous one will be ignored, and this one will be + # enabled. + # + -query = "\ + INSERT INTO nasreload \ + SET \ + nasipaddress = '%{NAS-IP-Address}', \ + reloadtime = ${...event_timestamp} \ + ON DUPLICATE KEY UPDATE reloadtime = ${...event_timestamp}" + + # If there are no open user sessions, then the previous query + # will return "no rows updated". The server will then fall through + # to the next query, which is just "yes, that's fine". + # + query = "SELECT true" + + } + + accounting-off { + query = "${..accounting-on.query}" + + query = "SELECT true" + } + + start { + # + # Insert a new record into the sessions table + # + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + NULL, \ + '0', \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '0', \ + '0', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}')" + + # + # Key constraints prevented us from inserting a new session, + # use the alternate query to update an existing session. + # + query = "\ + UPDATE ${...acct_table1} SET \ + acctstarttime = ${...event_timestamp}, \ + acctupdatetime = ${...event_timestamp}, \ + connectinfo_start = '%{Connect-Info}', \ + class = '%{Class}' \ + WHERE acctuniqueid = '%{Acct-Unique-Session-Id}'" + } + + interim-update { + # + # Update an existing session and calculate the interval + # between the last data we received for the session and this + # update. This can be used to find stale sessions. + # + query = "\ + UPDATE ${...acct_table1} \ + SET \ + acctupdatetime = (@acctupdatetime_old:=acctupdatetime), \ + acctupdatetime = ${...event_timestamp}, \ + acctinterval = ${...event_timestamp_epoch} - \ + UNIX_TIMESTAMP(@acctupdatetime_old), \ + framedipaddress = '%{Framed-IP-Address}', \ + framedipv6address = '%{Framed-IPv6-Address}', \ + framedipv6prefix = '%{Framed-IPv6-Prefix}', \ + framedinterfaceid = '%{Framed-Interface-Id}', \ + delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ + acctsessiontime = %{&Acct-Session-Time || 'NULL'}, \ + acctinputoctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + acctoutputoctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + class = '%{Class}' \ + WHERE acctuniqueid = '%{Acct-Unique-Session-Id}'" + + # + # The update condition matched no existing sessions. Use + # the values provided in the update to create a new session. + # + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + FROM_UNIXTIME(${...event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ + ${...event_timestamp}, \ + NULL, \ + %{&Acct-Session-Time || 'NULL'}, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ + '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}')" + } + + stop { + # + # Session has terminated, update the stop time and statistics. + # + query = "\ + UPDATE ${...acct_table2} SET \ + acctstoptime = ${...event_timestamp}, \ + acctsessiontime = %{&Acct-Session-Time || 'NULL'}, \ + acctinputoctets = '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ + acctoutputoctets = '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ + acctterminatecause = '%{Acct-Terminate-Cause}', \ + connectinfo_stop = '%{Connect-Info}', \ + class = '%{Class}' \ + WHERE acctuniqueid = '%{Acct-Unique-Session-Id}'" + + # + # The update condition matched no existing sessions. Use + # the values provided in the update to create a new session. + # + query = "\ + INSERT INTO ${...acct_table2} \ + (${..column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + FROM_UNIXTIME(${...event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + %{&Acct-Session-Time || 'NULL'}, \ + '%{Acct-Authentic}', \ + '', \ + '%{Connect-Info}', \ + '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ + '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Acct-Terminate-Cause}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}')" } } @@ -393,21 +392,27 @@ accounting { ####################################################################### # Authentication Logging Queries ####################################################################### -# postauth_query - Insert some info after authentication +# send queries - Insert some info after authentication ####################################################################### -post-auth { +send { # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/post-auth.sql - query = "\ - INSERT INTO ${..postauth_table} \ - (username, pass, reply, authdate, class) \ - VALUES ( \ - '%{SQL-User-Name}', \ - '%{&User-Password || &Chap-Password}', \ - '%{reply.Packet-Type}', \ - '%S.%M', \ - '%{reply.Class}')" + access-accept { + query = "\ + INSERT INTO ${...postauth_table} \ + (username, pass, reply, authdate, class) \ + VALUES ( \ + '%{SQL-User-Name}', \ + '%{&User-Password || &Chap-Password}', \ + '%{reply.Packet-Type}', \ + '%S.%M', \ + '%{reply.Class}')" + } + + access-reject { + query = "${..access-accept.query}" + } } diff --git a/raddb/mods-config/sql/main/oracle/queries.conf b/raddb/mods-config/sql/main/oracle/queries.conf index c894b29646..b9093847a0 100644 --- a/raddb/mods-config/sql/main/oracle/queries.conf +++ b/raddb/mods-config/sql/main/oracle/queries.conf @@ -109,284 +109,283 @@ group_membership_query = "\ # Accounting and Post-Auth Queries ####################################################################### # These queries insert/update accounting and authentication records. -# The query to use is determined by the value of 'reference'. -# This value is used as a configuration path and should resolve to one -# or more 'query's. If reference points to multiple queries, and a query -# fails, the next query is executed. +# The query to use is determined by the name of the section the module +# is called from. # -# Behaviour is identical to the old 1.x/2.x module, except we can now -# fail between N queries, and query selection can be based on any -# combination of attributes, or custom 'Acct-Status-Type' values. +# e.g. when called from `accouting Start`, the contents of +# +# accounting { +# start {} +# } +# +# will be read, and any "query" entries will be run in sequence +# until one returns a positive number of modified rows. ####################################################################### accounting { - reference = "%tolower(type.%{Acct-Status-Type}.query)" - # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. -# logfile = ${logdir}/accounting.sql - - type { - accounting-on { - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctStopTime = ${....event_timestamp}, \ - AcctSessionTime = ROUND((${....event_timestamp} - \ - TO_DATE(TO_CHAR(acctstarttime, 'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss'))*86400), \ - AcctTerminateCause='%{&Acct-Terminate-Cause || \'NAS-Reboot\'}', \ - AcctStopDelay = %{&Acct-Delay-Time || 0}, \ - Class = '%{Class}' \ - WHERE AcctStopTime IS NULL \ - AND NASIPAddress = '%{NAS-IP-Address}' \ - AND AcctStartTime <= ${....event_timestamp}" +# logfile = ${logdir}/accounting.sql - # - # If there are no open user sessions, then the previous query - # will return "no rows updated". The server will then fall through - # to the next query, which is just "yes, that's fine". - # - query = "SELECT 1 from dual" - } + accounting-on { + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctStopTime = ${...event_timestamp}, \ + AcctSessionTime = ROUND((${...event_timestamp} - \ + TO_DATE(TO_CHAR(acctstarttime, 'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss'))*86400), \ + AcctTerminateCause='%{&Acct-Terminate-Cause || \'NAS-Reboot\'}', \ + AcctStopDelay = %{&Acct-Delay-Time || 0}, \ + Class = '%{Class}' \ + WHERE AcctStopTime IS NULL \ + AND NASIPAddress = '%{NAS-IP-Address}' \ + AND AcctStartTime <= ${...event_timestamp}" - accounting-off { - query = "${..accounting-on.query}" + # + # If there are no open user sessions, then the previous query + # will return "no rows updated". The server will then fall through + # to the next query, which is just "yes, that's fine". + # + query = "SELECT 1 from dual" + } - query = "SELECT 1 from dual" - } + accounting-off { + query = "${..accounting-on.query}" - start { - query = "\ - INSERT INTO ${....acct_table1} (\ - RadAcctId, \ - AcctSessionId, \ - AcctUniqueId, \ - UserName, \ - Realm, \ - NASIPAddress, \ - NASPortId, \ - NASPortType, \ - AcctStartTime, \ - AcctStopTime, \ - AcctSessionTime, \ - AcctAuthentic, \ - ConnectInfo_start, \ - ConnectInfo_stop, \ - AcctInputOctets, \ - AcctOutputOctets, \ - CalledStationId, \ - CallingStationId, \ - AcctTerminateCause, \ - ServiceType, \ - FramedProtocol, \ - FramedIPAddress, \ - FramedIPv6Address, \ - FramedIPv6Prefix, \ - FramedInterfaceId, \ - DelegatedIPv6Prefix, \ - AcctStartDelay, \ - AcctStopDelay, \ - Class) \ - VALUES(\ - '', \ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - NULL, \ - '0', \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - '', \ - '0', \ - '0', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Acct-Delay-Time}', \ - '0', \ - '%{Class}')" + query = "SELECT 1 from dual" + } - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctStartTime = ${....event_timestamp}, \ - AcctStartDelay = '%{&Acct-Delay-Time || 0}', \ - ConnectInfo_start = '%{Connect-Info}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ - AND AcctStopTime IS NULL" - } + start { + query = "\ + INSERT INTO ${...acct_table1} (\ + RadAcctId, \ + AcctSessionId, \ + AcctUniqueId, \ + UserName, \ + Realm, \ + NASIPAddress, \ + NASPortId, \ + NASPortType, \ + AcctStartTime, \ + AcctStopTime, \ + AcctSessionTime, \ + AcctAuthentic, \ + ConnectInfo_start, \ + ConnectInfo_stop, \ + AcctInputOctets, \ + AcctOutputOctets, \ + CalledStationId, \ + CallingStationId, \ + AcctTerminateCause, \ + ServiceType, \ + FramedProtocol, \ + FramedIPAddress, \ + FramedIPv6Address, \ + FramedIPv6Prefix, \ + FramedInterfaceId, \ + DelegatedIPv6Prefix, \ + AcctStartDelay, \ + AcctStopDelay, \ + Class) \ + VALUES(\ + '', \ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + NULL, \ + '0', \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '0', \ + '0', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Acct-Delay-Time}', \ + '0', \ + '%{Class}')" - interim-update { - query = "\ - UPDATE ${....acct_table1} \ - SET \ - FramedIPAddress = NULLIF('%{Framed-IP-Address}', ''), \ - FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', ''), \ - FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', ''), \ - FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ - DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', ''), \ - AcctSessionTime = '%{Acct-Session-Time}', \ - AcctInputOctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - AcctOutputOctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ - AND AcctStopTime IS NULL" + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctStartTime = ${...event_timestamp}, \ + AcctStartDelay = '%{&Acct-Delay-Time || 0}', \ + ConnectInfo_start = '%{Connect-Info}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ + AND AcctStopTime IS NULL" + } - query = "\ - INSERT into ${....acct_table1} (\ - RadAcctId, \ - AcctSessionId, \ - AcctUniqueId, \ - UserName, \ - Realm, \ - NASIPAddress, \ - NASPortId, \ - NASPortType, \ - AcctStartTime, \ - AcctSessionTime, \ - AcctAuthentic, \ - ConnectInfo_start, \ - AcctInputOctets, \ - AcctOutputOctets, \ - CalledStationId, \ - CallingStationId, \ - ServiceType, \ - FramedProtocol, \ - FramedIPAddress, \ - AcctStartDelay, \ - Class) \ - VALUES(\ - '', \ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - NULL, \ - '%{Acct-Session-Time}', \ - '%{Acct-Authentic}', \ - '', \ - '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ - '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '0', \ - '%{Class}')" - } + interim-update { + query = "\ + UPDATE ${...acct_table1} \ + SET \ + FramedIPAddress = NULLIF('%{Framed-IP-Address}', ''), \ + FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', ''), \ + FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', ''), \ + FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ + DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', ''), \ + AcctSessionTime = '%{Acct-Session-Time}', \ + AcctInputOctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + AcctOutputOctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ + AND AcctStopTime IS NULL" - stop { - query = "\ - UPDATE ${....acct_table2} \ - SET \ - AcctStopTime = ${....event_timestamp}, \ - AcctSessionTime = '%{Acct-Session-Time}', \ - AcctInputOctets = '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ - AcctOutputOctets = '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ - AcctTerminateCause = '%{Acct-Terminate-Cause}', \ - AcctStopDelay = '%{&Acct-Delay-Time || 0}', \ - ConnectInfo_stop = '%{Connect-Info}', \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ - AND AcctStopTime IS NULL" + query = "\ + INSERT into ${...acct_table1} (\ + RadAcctId, \ + AcctSessionId, \ + AcctUniqueId, \ + UserName, \ + Realm, \ + NASIPAddress, \ + NASPortId, \ + NASPortType, \ + AcctStartTime, \ + AcctSessionTime, \ + AcctAuthentic, \ + ConnectInfo_start, \ + AcctInputOctets, \ + AcctOutputOctets, \ + CalledStationId, \ + CallingStationId, \ + ServiceType, \ + FramedProtocol, \ + FramedIPAddress, \ + AcctStartDelay, \ + Class) \ + VALUES(\ + '', \ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + NULL, \ + '%{Acct-Session-Time}', \ + '%{Acct-Authentic}', \ + '', \ + '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ + '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '0', \ + '%{Class}')" + } - query = "\ - INSERT into ${....acct_table2} (\ - RadAcctId, \ - AcctSessionId, \ - AcctUniqueId, \ - UserName, \ - Realm, \ - NASIPAddress, \ - NASPortId, \ - NASPortType, \ - AcctStartTime, \ - AcctStopTime, \ - AcctSessionTime, \ - AcctAuthentic, \ - ConnectInfo_start, \ - ConnectInfo_stop, \ - AcctInputOctets, \ - AcctOutputOctets, \ - CalledStationId, \ - CallingStationId, \ - AcctTerminateCause, \ - ServiceType, \ - FramedProtocol, \ - FramedIPAddress, \ - AcctStartDelay, \ - AcctStopDelay, \ - Class) \ - VALUES(\ - '', \ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - NULL, \ - ${....event_timestamp}, \ - '%{Acct-Session-Time}', \ - '%{Acct-Authentic}', \ - '', \ - '%{Connect-Info}', \ - NULL, \ - '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ - '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Acct-Terminate-Cause}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '0', \ - '%{&Acct-Delay-Time || 0}', \ - '%{Class}')" - } + stop { + query = "\ + UPDATE ${...acct_table2} \ + SET \ + AcctStopTime = ${...event_timestamp}, \ + AcctSessionTime = '%{Acct-Session-Time}', \ + AcctInputOctets = '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ + AcctOutputOctets = '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ + AcctTerminateCause = '%{Acct-Terminate-Cause}', \ + AcctStopDelay = '%{&Acct-Delay-Time || 0}', \ + ConnectInfo_stop = '%{Connect-Info}', \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ + AND AcctStopTime IS NULL" - # - # No Acct-Status-Type == ignore the packet - # - accounting { - query = "SELECT 1 from dual" - } + query = "\ + INSERT into ${...acct_table2} (\ + RadAcctId, \ + AcctSessionId, \ + AcctUniqueId, \ + UserName, \ + Realm, \ + NASIPAddress, \ + NASPortId, \ + NASPortType, \ + AcctStartTime, \ + AcctStopTime, \ + AcctSessionTime, \ + AcctAuthentic, \ + ConnectInfo_start, \ + ConnectInfo_stop, \ + AcctInputOctets, \ + AcctOutputOctets, \ + CalledStationId, \ + CallingStationId, \ + AcctTerminateCause, \ + ServiceType, \ + FramedProtocol, \ + FramedIPAddress, \ + AcctStartDelay, \ + AcctStopDelay, \ + Class) \ + VALUES(\ + '', \ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + NULL, \ + ${...event_timestamp}, \ + '%{Acct-Session-Time}', \ + '%{Acct-Authentic}', \ + '', \ + '%{Connect-Info}', \ + NULL, \ + '%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}', \ + '%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Acct-Terminate-Cause}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '0', \ + '%{&Acct-Delay-Time || 0}', \ + '%{Class}')" } } ####################################################################### # Authentication Logging Queries ####################################################################### -# postauth_query - Insert some info after authentication +# send queries - Insert some info after authentication ####################################################################### -post-auth { +send { # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/post-auth.sql - query = "\ - INSERT INTO ${..postauth_table} \ - (username, pass, reply, authdate, class) \ - VALUES (\ - '%{User-Name}', \ - '%{&User-Password || &Chap-Password}', \ - '%{reply.Packet-Type}', \ - TO_TIMESTAMP('%S.%M','YYYY-MM-DDHH24:MI:SS.FF'), \ - '%{reply.Class}')" + + access-accept { + query = "\ + INSERT INTO ${...postauth_table} \ + (username, pass, reply, authdate, class) \ + VALUES (\ + '%{User-Name}', \ + '%{&User-Password || &Chap-Password}', \ + '%{reply.Packet-Type}', \ + TO_TIMESTAMP('%S.%M','YYYY-MM-DDHH24:MI:SS.FF'), \ + '%{reply.Class}')" + } + + access-reject { + query = "${..access-accept.query}" + } } diff --git a/raddb/mods-config/sql/main/postgresql/queries.conf b/raddb/mods-config/sql/main/postgresql/queries.conf index 9d616b2e84..db0aec4f8f 100644 --- a/raddb/mods-config/sql/main/postgresql/queries.conf +++ b/raddb/mods-config/sql/main/postgresql/queries.conf @@ -157,19 +157,20 @@ group_membership_query = "\ # Accounting and Post-Auth Queries ####################################################################### # These queries insert/update accounting and authentication records. -# The query to use is determined by the value of 'reference'. -# This value is used as a configuration path and should resolve to one -# or more 'query's. If reference points to multiple queries, and a query -# fails, the next query is executed. +# The query to use is determined by the name of the section the module +# is called from. # -# Behaviour is identical to the old 1.x/2.x module, except we can now -# fail between N queries, and query selection can be based on any -# combination of attributes, or custom 'Acct-Status-Type' values. +# e.g. when called from `accouting Start`, the contents of +# +# accounting { +# start {} +# } +# +# will be read, and any "query" entries will be run in sequence +# until one returns a positive number of modified rows. ####################################################################### accounting { - reference = "%tolower(type.%{&Acct-Status-Type || 'none'}.query)" - # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/accounting.sql @@ -203,259 +204,250 @@ accounting { DelegatedIpv6Prefix, \ Class" - type { - accounting-on { - - # - # "Bulk update" Accounting-On/Off strategy. - # - # Immediately terminate all sessions associated with a - # given NAS. - # - # Note: If a large number of sessions require closing - # then the bulk update may be take a long time to run - # and lock an excessive number of rows. See the - # strategy below for an alternative approach that does - # not touch the radacct session data. - # - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctStopTime = ${....event_timestamp}, \ - AcctUpdateTime = ${....event_timestamp}, \ - AcctSessionTime = (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime))), \ - AcctTerminateCause = '%{&Acct-Terminate-Cause || \'NAS-Reboot\'}', \ - Class = '%{Class}' \ - WHERE AcctStopTime IS NULL \ - AND NASIPAddress= '%{&NAS-IPv6-Address || &NAS-IP-Address}' \ - AND AcctStartTime <= ${....event_timestamp}" - - # - # "Lightweight" Accounting-On/Off strategy. - # - # Record the reload time of the NAS and let the - # administrator actually close the sessions in radacct - # out-of-band, if desired. - # - # Implementation advice, together with a stored - # procedure for closing sessions and a view showing - # the effective stop time of each session is provided - # in process-radacct.sql. - # - # To enable this strategy, just change the previous - # query to "-query", and this one to "query". The - # previous one will be ignored, and this one will be - # enabled. - # - -query = "\ - INSERT INTO nasreload (NASIPAddress, ReloadTime) \ - VALUES ('%{NAS-IP-Address}', ${....event_timestamp}) \ - ON CONFLICT ON (NASIPAddress) \ - DO UPDATE SET \ - ReloadTime = ${....event_timestamp}" - - # If there are no open user sessions, then the previous query - # will return "no rows updated". The server will then fall through - # to the next query, which is just "yes, that's fine". - # - query = "SELECT true" - - } - - accounting-off { - query = "${..accounting-on.query}" - - query = "SELECT true" - } - - start { - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES(\ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - NULLIF('%{Realm}', ''), \ - '%{&NAS-IPv6-Address || &NAS-IP-Address}', \ - NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - NULL, \ - 0, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - NULL, \ - 0, \ - 0, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - NULL, \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - NULLIF('%{Framed-IP-Address}', '')::inet, \ - NULLIF('%{Framed-IPv6-Address}', '')::inet, \ - NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ - NULLIF('%{Framed-Interface-Id}', ''), \ - NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ - '%{Class}') \ - ON CONFLICT (AcctUniqueId) \ - DO UPDATE \ - SET \ - AcctStartTime = ${....event_timestamp}, \ - AcctUpdateTime = ${....event_timestamp}, \ - ConnectInfo_start = '%{Connect-Info}', \ - Class = '%{Class}' \ - WHERE ${....acct_table1}.AcctUniqueId = '%{Acct-Unique-Session-Id}' \ - AND ${....acct_table1}.AcctStopTime IS NULL" - - # and again where we don't have "AND AcctStopTime IS NULL" - query = "\ - UPDATE ${....acct_table1} \ - SET \ - AcctStartTime = ${....event_timestamp}, \ - AcctUpdateTime = ${....event_timestamp}, \ - ConnectInfo_start = '%{Connect-Info}', \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" - } - - interim-update { - query = "\ - UPDATE ${....acct_table1} \ - SET \ - FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \ - FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \ - FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ - FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ - DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ - AcctSessionTime = %{&Acct-Session-Time || \'NULL\'}, \ - AcctInterval = (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM (COALESCE(AcctUpdateTime, AcctStartTime)))), \ - AcctUpdateTime = ${....event_timestamp}, \ - AcctInputOctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - AcctOutputOctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \ - AND AcctStopTime IS NULL" - - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES(\ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - NULLIF('%{Realm}', ''), \ - '%{&NAS-IPv6-Address || &NAS-IP-Address}', \ - NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - NULL, \ - %{&Acct-Session-Time || \'NULL\'}, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - NULL, \ - (%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets})::bigint, \ - (%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets})::bigint, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - NULL, \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - NULLIF('%{Framed-IP-Address}', '')::inet, \ - NULLIF('%{Framed-IPv6-Address}', '')::inet, \ - NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ - NULLIF('%{Framed-Interface-Id}', ''), \ - NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ - '%{Class}') \ - ON CONFLICT (AcctUniqueId) \ - DO NOTHING" - } - - stop { - query = "\ - UPDATE ${....acct_table2} \ - SET \ - AcctStopTime = ${....event_timestamp}, \ - AcctUpdateTime = ${....event_timestamp}, \ - AcctSessionTime = COALESCE(%{&Acct-Session-Time || \'NULL\'}, \ - (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ - AcctInputOctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - AcctOutputOctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - AcctTerminateCause = '%{Acct-Terminate-Cause}', \ - FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \ - FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \ - FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ - FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ - DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ - ConnectInfo_stop = '%{Connect-Info}', \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \ - AND AcctStopTime IS NULL" - - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES(\ - '%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - NULLIF('%{Realm}', ''), \ - '%{&NAS-IPv6-Address || &NAS-IP-Address}', \ - NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \ - '%{NAS-Port-Type}', \ - TO_TIMESTAMP(${....event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - NULLIF('%{Acct-Session-Time}', '')::bigint, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - NULL, \ - (%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets})::bigint, \ - (%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets})::bigint, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Acct-Terminate-Cause}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - NULLIF('%{Framed-IP-Address}', '')::inet, \ - NULLIF('%{Framed-IPv6-Address}', '')::inet, \ - NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ - NULLIF('%{Framed-Interface-Id}', ''), \ - NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ - '%{Class}') \ - ON CONFLICT (AcctUniqueId) \ - DO NOTHING" - - # and again where we don't have "AND AcctStopTime IS NULL" - query = "\ - UPDATE ${....acct_table2} \ - SET \ - AcctStopTime = ${....event_timestamp}, \ - AcctUpdateTime = ${....event_timestamp}, \ - AcctSessionTime = COALESCE(%{&Acct-Session-Time || \'NULL\'}, \ - (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ - AcctInputOctets = (%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets})::bigint, \ - AcctOutputOctets = (%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets})::bigint, \ - AcctTerminateCause = '%{Acct-Terminate-Cause}', \ - FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \ - FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \ - FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ - FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ - DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ - ConnectInfo_stop = '%{Connect-Info}', \ - Class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" - } + accounting-on { # - # No Acct-Status-Type == ignore the packet + # "Bulk update" Accounting-On/Off strategy. + # + # Immediately terminate all sessions associated with a + # given NAS. + # + # Note: If a large number of sessions require closing + # then the bulk update may be take a long time to run + # and lock an excessive number of rows. See the + # strategy below for an alternative approach that does + # not touch the radacct session data. + # + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctStopTime = ${...event_timestamp}, \ + AcctUpdateTime = ${...event_timestamp}, \ + AcctSessionTime = (${...event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime))), \ + AcctTerminateCause = '%{&Acct-Terminate-Cause || \'NAS-Reboot\'}', \ + Class = '%{Class}' \ + WHERE AcctStopTime IS NULL \ + AND NASIPAddress= '%{&NAS-IPv6-Address || &NAS-IP-Address}' \ + AND AcctStartTime <= ${...event_timestamp}" + # - none { - query = "SELECT true" - } + # "Lightweight" Accounting-On/Off strategy. + # + # Record the reload time of the NAS and let the + # administrator actually close the sessions in radacct + # out-of-band, if desired. + # + # Implementation advice, together with a stored + # procedure for closing sessions and a view showing + # the effective stop time of each session is provided + # in process-radacct.sql. + # + # To enable this strategy, just change the previous + # query to "-query", and this one to "query". The + # previous one will be ignored, and this one will be + # enabled. + # + -query = "\ + INSERT INTO nasreload (NASIPAddress, ReloadTime) \ + VALUES ('%{NAS-IP-Address}', ${...event_timestamp}) \ + ON CONFLICT ON (NASIPAddress) \ + DO UPDATE SET \ + ReloadTime = ${...event_timestamp}" + + # If there are no open user sessions, then the previous query + # will return "no rows updated". The server will then fall through + # to the next query, which is just "yes, that's fine". + # + query = "SELECT true" + + } + + accounting-off { + query = "${..accounting-on.query}" + + query = "SELECT true" + } + + start { + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + NULLIF('%{Realm}', ''), \ + '%{&NAS-IPv6-Address || &NAS-IP-Address}', \ + NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + NULL, \ + 0, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + NULL, \ + 0, \ + 0, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + NULL, \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + NULLIF('%{Framed-IP-Address}', '')::inet, \ + NULLIF('%{Framed-IPv6-Address}', '')::inet, \ + NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ + NULLIF('%{Framed-Interface-Id}', ''), \ + NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ + '%{Class}') \ + ON CONFLICT (AcctUniqueId) \ + DO UPDATE \ + SET \ + AcctStartTime = ${...event_timestamp}, \ + AcctUpdateTime = ${...event_timestamp}, \ + ConnectInfo_start = '%{Connect-Info}', \ + Class = '%{Class}' \ + WHERE ${...acct_table1}.AcctUniqueId = '%{Acct-Unique-Session-Id}' \ + AND ${...acct_table1}.AcctStopTime IS NULL" + + # and again where we don't have "AND AcctStopTime IS NULL" + query = "\ + UPDATE ${...acct_table1} \ + SET \ + AcctStartTime = ${...event_timestamp}, \ + AcctUpdateTime = ${...event_timestamp}, \ + ConnectInfo_start = '%{Connect-Info}', \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + } + + interim-update { + query = "\ + UPDATE ${...acct_table1} \ + SET \ + FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \ + FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \ + FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ + FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ + DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ + AcctSessionTime = %{&Acct-Session-Time || 'NULL'}, \ + AcctInterval = (${...event_timestamp_epoch} - EXTRACT(EPOCH FROM (COALESCE(AcctUpdateTime, AcctStartTime)))), \ + AcctUpdateTime = ${...event_timestamp}, \ + AcctInputOctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + AcctOutputOctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \ + AND AcctStopTime IS NULL" + + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + NULLIF('%{Realm}', ''), \ + '%{&NAS-IPv6-Address || &NAS-IP-Address}', \ + NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + NULL, \ + %{&Acct-Session-Time || 'NULL'}, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + NULL, \ + (%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets})::bigint, \ + (%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets})::bigint, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + NULL, \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + NULLIF('%{Framed-IP-Address}', '')::inet, \ + NULLIF('%{Framed-IPv6-Address}', '')::inet, \ + NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ + NULLIF('%{Framed-Interface-Id}', ''), \ + NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ + '%{Class}') \ + ON CONFLICT (AcctUniqueId) \ + DO NOTHING" + } + + stop { + query = "\ + UPDATE ${...acct_table2} \ + SET \ + AcctStopTime = ${...event_timestamp}, \ + AcctUpdateTime = ${...event_timestamp}, \ + AcctSessionTime = COALESCE(%{&Acct-Session-Time || 'NULL'}, \ + (${...event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ + AcctInputOctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + AcctOutputOctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + AcctTerminateCause = '%{Acct-Terminate-Cause}', \ + FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \ + FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \ + FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ + FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ + DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ + ConnectInfo_stop = '%{Connect-Info}', \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \ + AND AcctStopTime IS NULL" + + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES(\ + '%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + NULLIF('%{Realm}', ''), \ + '%{&NAS-IPv6-Address || &NAS-IP-Address}', \ + NULLIF('%{&NAS-Port-ID || &NAS-Port}', ''), \ + '%{NAS-Port-Type}', \ + TO_TIMESTAMP(${...event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + NULLIF('%{Acct-Session-Time}', '')::bigint, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + NULL, \ + (%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets})::bigint, \ + (%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets})::bigint, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Acct-Terminate-Cause}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + NULLIF('%{Framed-IP-Address}', '')::inet, \ + NULLIF('%{Framed-IPv6-Address}', '')::inet, \ + NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ + NULLIF('%{Framed-Interface-Id}', ''), \ + NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ + '%{Class}') \ + ON CONFLICT (AcctUniqueId) \ + DO NOTHING" + + # and again where we don't have "AND AcctStopTime IS NULL" + query = "\ + UPDATE ${...acct_table2} \ + SET \ + AcctStopTime = ${...event_timestamp}, \ + AcctUpdateTime = ${...event_timestamp}, \ + AcctSessionTime = COALESCE(%{&Acct-Session-Time || 'NULL'}, \ + (${...event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ + AcctInputOctets = (%{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets})::bigint, \ + AcctOutputOctets = (%{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets})::bigint, \ + AcctTerminateCause = '%{Acct-Terminate-Cause}', \ + FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \ + FramedIPv6Address = NULLIF('%{Framed-IPv6-Address}', '')::inet, \ + FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ + FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ + DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ + ConnectInfo_stop = '%{Connect-Info}', \ + Class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" } } @@ -463,21 +455,27 @@ accounting { ####################################################################### # Authentication Logging Queries ####################################################################### -# postauth_query - Insert some info after authentication +# send queries - Insert some info after authentication ####################################################################### -post-auth { +send { # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/post-auth.sql - query = "\ - INSERT INTO ${..postauth_table} \ - (username, pass, reply, authdate, class) \ - VALUES(\ - '%{User-Name}', \ - '%{&User-Password || &Chap-Password}', \ - '%{reply.Packet-Type}', \ - '%S.%M', \ - '%{reply.Class}')" + access-accept { + query = "\ + INSERT INTO ${...postauth_table} \ + (username, pass, reply, authdate, class) \ + VALUES(\ + '%{User-Name}', \ + '%{&User-Password || &Chap-Password}', \ + '%{reply.Packet-Type}', \ + '%S.%M', \ + '%{reply.Class}')" + } + + access-reject { + query = "${..access-accept.query}" + } } diff --git a/raddb/mods-config/sql/main/sqlite/queries.conf b/raddb/mods-config/sql/main/sqlite/queries.conf index 6f3b1ec21e..6d13cf0d9a 100644 --- a/raddb/mods-config/sql/main/sqlite/queries.conf +++ b/raddb/mods-config/sql/main/sqlite/queries.conf @@ -126,21 +126,22 @@ authorize_group_reply_query = "\ ORDER BY id" ####################################################################### -# Accounting and Post-Auth Queries +# Accounting and Send Queries ####################################################################### # These queries insert/update accounting and authentication records. -# The query to use is determined by the value of 'reference'. -# This value is used as a configuration path and should resolve to one -# or more 'query's. If reference points to multiple queries, and a query -# fails, the next query is executed. +# The query to use is determined by the name of the section the module +# is called from. # -# Behaviour is identical to the old 1.x/2.x module, except we can now -# fail between N queries, and query selection can be based on any -# combination of attributes, or custom 'Acct-Status-Type' values. +# e.g. when called from `accouting Start`, the contents of +# +# accounting { +# start {} +# } +# +# will be read, and any "query" entries will be run in sequence +# until one returns a positive number of modified rows. ####################################################################### accounting { - reference = "%tolower(type.%{Acct-Status-Type}.query)" - # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/accounting.sql @@ -174,247 +175,254 @@ accounting { delegatedipv6prefix, \ class" - type { - accounting-on { - - # - # "Bulk update" Accounting-On/Off strategy. - # - # Immediately terminate all sessions associated with a - # given NAS. - # - # Note: If a large number of sessions require closing - # then the bulk update may be take a long time to run - # and lock an excessive number of rows. See the - # strategy below for an alternative approach that does - # not touch the radacct session data. - # - query = "\ - UPDATE ${....acct_table1} \ - SET \ - acctstoptime = ${....event_timestamp}, \ - acctsessiontime = \ - (${....event_timestamp_epoch} \ - - acctstarttime), \ - acctterminatecause = '%{Acct-Terminate-Cause}', \ - class = '%{Class}' \ - WHERE acctstoptime IS NULL \ - AND nasipaddress = '%{NAS-IP-Address}' \ - AND acctstarttime <= ${....event_timestamp}" - - # "Lightweight" Accounting-On/Off strategy. - # - # Record the reload time of the NAS and let the - # administrator actually close the sessions in radacct - # out-of-band, if desired. - # - # Implementation advice, together with a stored - # procedure for closing sessions and a view showing - # the effective stop time of each session is provided - # in process-radacct.sql. - # - # To enable this strategy, just change the previous - # query to "-query", and this one to "query". The - # previous one will be ignored, and this one will be - # enabled. - # - -query = "\ - INSERT OR REPLACE INTO nasreload (nasipaddress, reloadtime) \ - VALUES ('%{NAS-IP-Address}', ${....event_timestamp})" - - # - # If there are no open user sessions, then the previous query - # will return "no rows updated". The server will then fall through - # to the next query, which is just "yes, that's fine". - # - query = "SELECT true" - - } - - accounting-off { - query = "${..accounting-on.query}" - - query = "SELECT true" - } - - start { - # - # Insert a new record into the sessions table - # - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES \ - ('%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - NULL, \ - '0', \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - '', \ - '0', \ - '0', \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}')" - - # - # Key constraints prevented us from inserting a new session, - # use the alternate query to update an existing session. - # - query = "\ - UPDATE ${....acct_table1} SET \ - acctstarttime = ${....event_timestamp}, \ - acctupdatetime = ${....event_timestamp}, \ - connectinfo_start = '%{Connect-Info}', \ - class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" - } - - interim-update { - # - # Update an existing session and calculate the interval - # between the last data we received for the session and this - # update. This can be used to find stale sessions. - # - query = "\ - UPDATE ${....acct_table1} \ - SET \ - acctupdatetime = ${....event_timestamp}, \ - acctinterval = 0, \ - framedipaddress = '%{Framed-IP-Address}', \ - framedipv6address = '%{Framed-IPv6-Address}', \ - framedipv6prefix = '%{Framed-IPv6-Prefix}', \ - framedinterfaceid = '%{Framed-Interface-Id}', \ - delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ - acctsessiontime = %{&Acct-Session-Time || \'NULL\'}, \ - class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" - - # - # The update condition matched no existing sessions. Use - # the values provided in the update to create a new session. - # - query = "\ - INSERT INTO ${....acct_table1} \ - (${...column_list}) \ - VALUES \ - ('%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - (${....event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ - ${....event_timestamp}, \ - NULL, \ - %{&Acct-Session-Time || \'NULL\'}, \ - '%{Acct-Authentic}', \ - '%{Connect-Info}', \ - '', \ - %{&Acct-Input-Gigawords || 0} << 32 | %{&Acct-Input-Octets || 0}, \ - %{&Acct-Output-Gigawords || 0} << 32 | %{&Acct-Output-Octets || 0}, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}')" - } - - stop { - # - # Session has terminated, update the stop time and statistics. - # - query = "\ - UPDATE ${....acct_table2} SET \ - acctstoptime = ${....event_timestamp}, \ - acctsessiontime = %{&Acct-Session-Time || \'NULL\'}, \ - acctinputoctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - acctoutputoctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - acctterminatecause = '%{Acct-Terminate-Cause}', \ - connectinfo_stop = '%{Connect-Info}', \ - class = '%{Class}' \ - WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" - - # - # The update condition matched no existing sessions. Use - # the values provided in the update to create a new session. - # - query = "\ - INSERT INTO ${....acct_table2} \ - (${...column_list}) \ - VALUES \ - ('%{Acct-Session-Id}', \ - '%{Acct-Unique-Session-Id}', \ - '%{SQL-User-Name}', \ - '%{Realm}', \ - '%{NAS-IP-Address}', \ - '%{&NAS-Port-ID || &NAS-Port}', \ - '%{NAS-Port-Type}', \ - (${....event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ - ${....event_timestamp}, \ - ${....event_timestamp}, \ - %{&Acct-Session-Time || \'NULL\'}, \ - '%{Acct-Authentic}', \ - '', \ - '%{Connect-Info}', \ - %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ - %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ - '%{Called-Station-Id}', \ - '%{Calling-Station-Id}', \ - '%{Acct-Terminate-Cause}', \ - '%{Service-Type}', \ - '%{Framed-Protocol}', \ - '%{Framed-IP-Address}', \ - '%{Framed-IPv6-Address}', \ - '%{Framed-IPv6-Prefix}', \ - '%{Framed-Interface-Id}', \ - '%{Delegated-IPv6-Prefix}', \ - '%{Class}')" - } + accounting-on { + + # + # "Bulk update" Accounting-On/Off strategy. + # + # Immediately terminate all sessions associated with a + # given NAS. + # + # Note: If a large number of sessions require closing + # then the bulk update may be take a long time to run + # and lock an excessive number of rows. See the + # strategy below for an alternative approach that does + # not touch the radacct session data. + # + query = "\ + UPDATE ${...acct_table1} \ + SET \ + acctstoptime = ${...event_timestamp}, \ + acctsessiontime = \ + (${...event_timestamp_epoch} \ + - acctstarttime), \ + acctterminatecause = '%{Acct-Terminate-Cause}', \ + class = '%{Class}' \ + WHERE acctstoptime IS NULL \ + AND nasipaddress = '%{NAS-IP-Address}' \ + AND acctstarttime <= ${...event_timestamp}" + + # "Lightweight" Accounting-On/Off strategy. + # + # Record the reload time of the NAS and let the + # administrator actually close the sessions in radacct + # out-of-band, if desired. + # + # Implementation advice, together with a stored + # procedure for closing sessions and a view showing + # the effective stop time of each session is provided + # in process-radacct.sql. + # + # To enable this strategy, just change the previous + # query to "-query", and this one to "query". The + # previous one will be ignored, and this one will be + # enabled. + # + -query = "\ + INSERT OR REPLACE INTO nasreload (nasipaddress, reloadtime) \ + VALUES ('%{NAS-IP-Address}', ${...event_timestamp})" + + # + # If there are no open user sessions, then the previous query + # will return "no rows updated". The server will then fall through + # to the next query, which is just "yes, that's fine". + # + query = "SELECT true" + + } + + accounting-off { + query = "${..accounting-on.query}" + + query = "SELECT true" + } + + start { + # + # Insert a new record into the sessions table + # + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + NULL, \ + '0', \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + '0', \ + '0', \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}')" + + # + # Key constraints prevented us from inserting a new session, + # use the alternate query to update an existing session. + # + query = "\ + UPDATE ${...acct_table1} SET \ + acctstarttime = ${...event_timestamp}, \ + acctupdatetime = ${...event_timestamp}, \ + connectinfo_start = '%{Connect-Info}', \ + class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + } + + interim-update { + # + # Update an existing session and calculate the interval + # between the last data we received for the session and this + # update. This can be used to find stale sessions. + # + query = "\ + UPDATE ${...acct_table1} \ + SET \ + acctupdatetime = ${...event_timestamp}, \ + acctinterval = 0, \ + framedipaddress = '%{Framed-IP-Address}', \ + framedipv6address = '%{Framed-IPv6-Address}', \ + framedipv6prefix = '%{Framed-IPv6-Prefix}', \ + framedinterfaceid = '%{Framed-Interface-Id}', \ + delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ + acctsessiontime = %{&Acct-Session-Time || 'NULL'}, \ + class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + + # + # The update condition matched no existing sessions. Use + # the values provided in the update to create a new session. + # + query = "\ + INSERT INTO ${...acct_table1} \ + (${..column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + (${...event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ + ${...event_timestamp}, \ + NULL, \ + %{&Acct-Session-Time || 'NULL'}, \ + '%{Acct-Authentic}', \ + '%{Connect-Info}', \ + '', \ + %{&Acct-Input-Gigawords || 0} << 32 | %{&Acct-Input-Octets || 0}, \ + %{&Acct-Output-Gigawords || 0} << 32 | %{&Acct-Output-Octets || 0}, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}')" + } + + stop { + # + # Session has terminated, update the stop time and statistics. + # + query = "\ + UPDATE ${...acct_table2} SET \ + acctstoptime = ${...event_timestamp}, \ + acctsessiontime = %{&Acct-Session-Time || 'NULL'}, \ + acctinputoctets = %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + acctoutputoctets = %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + acctterminatecause = '%{Acct-Terminate-Cause}', \ + connectinfo_stop = '%{Connect-Info}', \ + class = '%{Class}' \ + WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" + + # + # The update condition matched no existing sessions. Use + # the values provided in the update to create a new session. + # + query = "\ + INSERT INTO ${...acct_table2} \ + (${..column_list}) \ + VALUES \ + ('%{Acct-Session-Id}', \ + '%{Acct-Unique-Session-Id}', \ + '%{SQL-User-Name}', \ + '%{Realm}', \ + '%{NAS-IP-Address}', \ + '%{&NAS-Port-ID || &NAS-Port}', \ + '%{NAS-Port-Type}', \ + (${...event_timestamp_epoch} - %{&Acct-Session-Time || 0}), \ + ${...event_timestamp}, \ + ${...event_timestamp}, \ + %{&Acct-Session-Time || 'NULL'}, \ + '%{Acct-Authentic}', \ + '', \ + '%{Connect-Info}', \ + %{(((uint64) &Acct-Input-Gigawords) << 32) | (uint64) &Acct-Input-Octets}, \ + %{(((uint64) &Acct-Output-Gigawords) << 32) | (uint64) &Acct-Output-Octets}, \ + '%{Called-Station-Id}', \ + '%{Calling-Station-Id}', \ + '%{Acct-Terminate-Cause}', \ + '%{Service-Type}', \ + '%{Framed-Protocol}', \ + '%{Framed-IP-Address}', \ + '%{Framed-IPv6-Address}', \ + '%{Framed-IPv6-Prefix}', \ + '%{Framed-Interface-Id}', \ + '%{Delegated-IPv6-Prefix}', \ + '%{Class}')" } } + ####################################################################### # Authentication Logging Queries ####################################################################### -# postauth_query - Insert some info after authentication +# send queries - Insert some info after authentication ####################################################################### -post-auth { +send { # Write SQL queries to a logfile. This is potentially useful for bulk inserts # when used with the rlm_sql_null driver. # logfile = ${logdir}/post-auth.sql + access-accept { + + query = "UPDATE ${...postauth_table} SET username = '%{User-Name}' WHERE 1 = 0" + + query = "\ + INSERT INTO ${...postauth_table} \ + (username, pass, reply, authdate, class) \ + VALUES ( \ + '%{SQL-User-Name}', \ + '%{&User-Password || &Chap-Password}', \ + '%{reply.Packet-Type}', \ + '%S.%M', \ + '%{reply.Class}')" + } - query = "\ - INSERT INTO ${..postauth_table} \ - (username, pass, reply, authdate, class) \ - VALUES ( \ - '%{SQL-User-Name}', \ - '%{&User-Password || &Chap-Password}', \ - '%{reply.Packet-Type}', \ - '%S.%M', \ - '%{reply.Class}')" + access-reject { + query = "${..access-accept.query}" + } }