I implemented what I would call 'automatic profile switching' for an AAA system that uses my aaarails project with their internal NMS.
Customers which exceed a certain data credit should get a profile assigned that limits their bandwidth until they re-charge.
I use the standard postgres schema for freeradius, so this solution might be useful to you if you happen to run a similar setup and are in need for an idea.
TD;DR: Create two (one normal, one for limited services) profiles per user. Change authorize_reply_query in freeradius to select the right profile based on the state of a user. Change the state via trigger-functions in the database that react to the accounting inserts/updates.
This is how I did it:
Add a data_credit field per 'user' (radchecks table) and some columns to hold data for bandwidth calculations:
ALTER TABLE radchecks ADD COLUMN data_credit BIGINT; ALTER TABLE radchecks ADD COLUMN in_octets BIGINT DEFAULT 0; ALTER TABLE radchecks ADD COLUMN in_octets_last BIGINT DEFAULT 0; ...
ALTER TABLE radaccts ADD COLUMN radchecks_id INTEGER; CREATE OR REPLACE FUNCTION radius_find_radchecks_from_whatever() RETURNS trigger AS $BODY$ ...do your magic... NEW.radchecks_id = the_id_you_extracted_based_on_the_accounting_data; RETURN NEW; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; CREATE TRIGGER trigger_insert_radaccts BEFORE INSERT ON radaccts FOR EACH ROW EXECUTE PROCEDURE radius_find_radchecks_from_whatever();
CREATE OR REPLACE FUNCTION radaccts_counters() RETURNS TRIGGER AS $$ DECLARE ... BEGIN ... new_in = NEW.acctinputoctets; ... if (new_in IS NOT NULL) then ... UPDATE radchecks SET in_octets = (in_octets+diff_in), in_octets_last = new_in WHERE id = NEW.radchecks_id; END IF; ... UPDATE radchecks SET credit_counter = (credit_counter - diff_in - diff_out) WHERE id = NEW.radchecks_id; ... RETURN NEW; END; $$ LANGUAGE 'plpgsql'; CREATE TRIGGER trigger_insert_radaccts_counters AFTER INSERT OR UPDATE ON radaccts FOR EACH ROW EXECUTE PROCEDURE radaccts_counters();
SELECT radreplies.id, radreplies.UserName, radreplies.cAttribute, radreplies.cValue, radreplies.Op FROM radreplies LEFT JOIN radchecks ON radreplies.Username=radchecks.Username WHERE radchecks.Username = '${User-Name}' AND radreplies.priority = (radchecks.credit_counter > 0)::int ORDER BY radreplies.id(in other words: if the credit_counter of a user goes below 1, the freeradius system switches over to the shadow profile of that user.)
IT-Dienstleistungen
Drostestrasse 3
53819 Neunkirchen
Germany
USt-Id-Nr.: DE203610693
web: https://beastiebytes.com/
email: sven@beastiebytes.com
skype: sven2342
phone: +49 22 47 90 80 250
mobile/signal: +49 157 3131 4424
xing,
google+
OTR-Fingerprint: 7849BD93B65F9E4BC1206B06C09B7445721063BC
GPG/PGP-Key: (pub 4096R/069DD13C 2014-02-13) local copy pgp.mit.edu
GPG/PGP-Key: fingerprint: 9BAD 94D3 9176 5BD1 F64F 542E 37E4 3542 069D D13C