Radius and Mysql with hourly Accounting

I've been setting up a Radius server (freeradius) to handle auth'ing users on our community wifi network. It made sense to get the data (users, accounting etc.) into Mysql and its is relatively easy to compile Freeradius with Mysql support. I used MacPorts and had to use this patch

 

The user authorisation worked with very little effort. Theres some useful information on getting it set up on the Freeradius Wiki.

 

However, the accounting was more difficult. The NAS (Network Access Servers) that we use (Ubiquiti Rocket M5's) dont sent the "NAS-Port" number in the data packet they send to the radius server (at leaste, not in the current beta firmeware). As the server uses this to create a hash to uniquely identify the session, we got lots of duplicate rows in Mysql and several rows were getting updated by the "Interim-Update" packets that our NAS send every ten minutes.

 

Luckily there was a simple solution. Freeradius includes several configuration files for different database servers. I noticed that some of the others had a much more robust mechanism for updating the accounting mysql table ("radacct" is the default table name). 

I'm using the default "dialup.conf" as the configuration file for the various SQL statements. By appending "AND acctstoptime IS NULL" to the accounting_update_query and the accounting_start_query_alt statements, the problem was resolved. I have no idea why this is the default for the Mysql config that ships with radius as this is how the statemenst for Oracle and some of the other DBS servers are configured. ...Maybe I'm mising something(I'm new to radius), but its working for me at the moment.

 

I wnated to be able to generate graphs of hour by hour bandwidth usage for our network usage. Our NAS send updates every ten minutes so I knoew this showuld be possible. However the Radius accounting table only maintains a cumulative total for each session, so it was goung to need a separate approach.

 

Having done some research I realised that using a Myql trigger was the way to go. Everytime my radacct table was updated (i.e. every ten minutes for each session) the trigger could invoke a routine to store the data in a separate stats table. The sql for the stats table is below.

 

DROP TABLE IF EXISTS `user_stats`;
    CREATE TABLE `user_stats` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `radacct_id` int(11) NOT NULL,
    `acctsessionid` varchar(64) NOT NULL,
    `acctuniqueid` varchar(32) NOT NULL,
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `acctinputoctets` bigint(20) NOT NULL,
    `acctoutputoctets` bigint(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

 

I'm actually duplicating quite a bit of unecessart data here(e.g. acctsessionid and acctuniqueid) are both available in the radact table. radacct_id is a reference to the 'parent' record.

 

The trigger was really easy:

delimiter $$
    CREATE TRIGGER radacct_after_update
    AFTER update ON radacct FOR EACH ROW BEGIN
    INSERT INTO user_stats 
      SET 
      radacct_id = OLD.radacctid, 
      acctsessionid=OLD.acctsessionid,
      acctuniqueid = OLD.acctuniqueid,
      acctinputoctets = (NEW.acctinputoctets - OLD.acctinputoctets), 
      acctoutputoctets = (NEW.acctoutputoctets - OLD.acctoutputoctets)
    END$$ 
    delimiter ;

 

The trick is to subtract the old cumlative data totals from the new - that gives the total for the period in question.

 

This is still very much a work-in-progress but I hope it helps someone!

 

Leave a comment

4:30am Technology Blog


Alistair Fleming
By Alistair Fleming

Automatically pause iTunes when your phone leaves the building

Heres a neat way to have iTunes automatically pause iTunes when (you and) your phone moves out of bluetooth range. It will then resume playing when you return.

You may already be familiar with Proximity, a Mac Application that will trigger an applescript based on whether it detects your phones bluetooth signal.

You'll need to install this first: http://code.google.com/p/reduxcomputing-proximity/

 

Once Proximity is installed, fire up Apple Script Editor and create the script that will run when you move out of range.

The nice theing about this is that it will neatly fade down iTunes and its sister script (that will run when you come back into range) fades the volume back up to the same level.

 

The scripts also use a system default to decide whether to trigger iTunes to resume playing. The nice thing about this is that iTunes will only resume playing, if it was Proximity that caused it to pause...so iTunes wont suddenly and unexpectedly start playing. This was a big issue with other scripts I had used.

 

(* 
db iTunes Fade-in/Fade-out
By Al Fleming, 430am.com
Based on ideas from David Battino, Batmosphere.com, Doug's AppleScripts and Mac OS Hints
Thanks to Jacob Rus for the "global" tip

This script fades out iTunes if it's playing and fades it in if it's stopped.
*)

global okflag
set okflag to false

set iChatRunning to false
set front_app to (path to frontmost application as Unicode text) -- So we can switch back to this after running the fade

-- check if iTunes is running 
tell application "System Events"
  if process "iTunes" exists then
    set okflag to true --iTunes is running
  end if
  if exists process "iChat" then
    set iChatRunning to true
  end if
end tell

if okflag is true then
  try
    
    tell application "iTunes"
      
      set currentvolume to the sound volume
      if (player state is playing) then
        do shell script "defaults write 'com.430am.iTuneswasrunning' wasrunning \"true\""
        repeat
          --Fade down 
          repeat with i from currentvolume to 0 by -1 --try by -4 on slower Macs
            set the sound volume to i
            delay 0.03 -- Adjust this to change fadeout duration (delete this line on slower Macs)
          end repeat
          pause
          --Restore original volume
          set the sound volume to currentvolume
          exit repeat
        end repeat
      end if
    end tell
    tell application front_app
      activate
    end tell
  on error
    beep
  end try
end if

if iChatRunning is true then
  tell application "iChat"
    log out
  end tell
end if

 

You'll notice that this also logs out of of iChat as well. If you dont want that then remove that part of the script.

 

Save this as a script called proximity_away.scpt

 

Now create a new script. This one will be triggered when you arrive back:

 

 

 

 

tell application "System Events"
  if process "iTunes" exists then
    set okflag to true --iTunes is running
    set wasrunning to do shell script "defaults read 'com.430am.iTuneswasrunning' wasrunning"
  end if
  if exists process "iChat" then
    set iChatRunning to true
  end if
end tell

if okflag is true then
  try
    tell application "iTunes"
      set currentvolume to the sound volume
      if (player state is playing) then
        -- could add functions here for when you arrive back and itunes is already playing
      else
        --Fade up 
        if (wasrunning is "true") then
          set the sound volume to 0
          play
          repeat with i from 0 to currentvolume by 1 --try by -4 on slower Macs
            set the sound volume to i
            delay 0.03 -- Adjust this to change fadeout duration (delete this line on slower Macs)
          end repeat
          do shell script "defaults write 'com.430am.iTuneswasrunning' wasrunning \"false\""
          (*play
        repeat with j from 0 to currentvolume by 2 --try by 4 on slower Macs
          set the sound volume to j
        end repeat*)
        end if
      end if
    end tell
    tell application front_app
      activate
    end tell
  on error
    beep
  end try
end if
if iChatRunning is true then
  tell application "iChat"
    log in
  end tell
end if


 

Saving this as proximity_here.scpt

 

Now open up the Proximity preferences and set the Out Of Range scrip to the proximity_away.scpt script and the In Range to the proximity_here.scpt

 

I changed the Device monitoring time to 10 seconds (not sure whether theres significant CPU overhead for this).

 

Leave a comment

CSS Expandable Div with rounded corners - using only one element!

7th October 2010

Having nicely-styled, expandable, divs using rounded corners, drop shadows or whatever has always been difficult to achieve without either resorting to using the CSS3 border-radius (which isnt fully supported yet) or using complex nested divs and background images.

 

I came across a posting on Nicolas Gallaghers site about using the CSS :before and :after psuedo elements to create interesting effects. These elements are CSS 2.1 so they should be supported by all modern browser incarnations. I realised that the same technique could be used to create expandable divs with rounded corners and/or drop shadows using only one element.

e.g.:

<div id="expandbox">Content here</div>

 

Check out the demo here. You can get the method by looking at the source and linked css

Leave a comment

New Technology - Node.js

9th September 2010

Every once in a while something new comes along that gets us excited. Node.js is one of those.

 

Node.js is described as "A toolkit for writing extremely high performance non-blocking event driven network servers in JavaScript". It is an evented I/O Framework that is built on top of Google's V8 javascript engine which already has a reputation for being blindingly fast.

 

But most importantly, it allows developers to create high performance network servers with just a few lines of javascript code.

 

Server-side javascript is becoming more popular and with the performance that Node.js can give, the arguments for using it are stronger than ever.

 

Furthermore, Ryan Dahl, the creator, has focussed on making Node.js completely event driven and non-blocking. A traditional web-server thread would spend much of its time waiting for, say, a database query to complete before it can send the response back to the browser. This ties up a thread doing essentially nothing and is a serious restriction to scalability. Because Node.js is event driven, processes can get on with doing other stuff and only go back to delivering the results of the database query when they are ready.

 

in a nutshell, this makes it extremely fast and scaleable.

 

Node.js also has a plug-in architecture and theres an ever-growing list of modules to enhance and expand its capabilities.

 

Node.js is low-level. That is to say, it doesnt do much out of the box. But you can "write" your own webserver with just a few lines of code.

 

Example of a (very!) basic web-server listening on port 8080:

var http = require('http');
http.createServer(function (request, response) {
	response.writeHead(200, {'Content-Type': 'text/plain'});
	response.end('Hello World\n');
}).listen(8080);
console.log('Server running at http://127.0.0.1:8080/');

 

As Node.js supports calls to the file-system, code to serve static files is also very easy:

 

var sys = require("sys"),
    http = require("http"),
    url = require("url"),
    path = require("path"),
    fs = require("fs");

http.createServer(function(request, response) {
    var uri = url.parse(request.url).pathname;
    var filename = path.join(process.cwd(), uri);
    path.exists(filename, function(exists) {
    	if(!exists) {
    		response.writeHead(404, {"Content-Type": "text/plain"});
    		response.write("404 Not Found\n");
    		response.end();
    		return;
    	}

    	fs.readFile(filename, "binary", function(err, file) {
    		if(err) {
    			response.writeHead(500, {"Content-Type": "text/plain"});
    			response.write(err + "\n");
    			response.end();
    			return;
    		}

    		response.writeHead(200);
    		response.write(file, "binary");
    		response.end();
    	});
    });
}).listen(8080);

sys.puts("Server running at http://localhost:8080/");

 

Obviously theres a lot more to a production-level server than this code snippet but the good news is that there a whole raft of 3rd party modules and frameworks to handle things like logging and mime-types etc.

 

So, if you know javascript already, give node.js a whirl!

Leave a comment