Last week I saw Celtic Woman in concert - they put on an excellent performance, though the audience around me left a lot to be desired.
Onto more relevant topics. It turns out that building a MAC address + IP address + authentication application is actually easier than it sounds. The challenge is hovering near the network stack, specifically with the firewalls.
Here's the deal:
Ubuntu - Everyone's favorite Linux is several versions behind on both iptables and shorewall, not to mention that ipset isn't even in the kernel/package tree. If you want to, you can hack at it and compile in support.
FreeBSD - While it has the benefit of pick-your favorite firewall (pf, ipfw, firewall, etc...) it lacks layer2 filtering in a pretty big way. Gleb Kurtsou wrote a kernel patch as part of the Summer of Code '08 but sadly, it's not ready yet (and doesn't seem to work seamlessly with 8.0 Stable).
Debian - Well, according to the debian package repository it has ipset, iptables, and shorewall all at reasonably high version numbers. I'm going down this road now and I'll let you know how it turns out when I'm finished.
The big challenge at this stage is figuring out how to track valid IPs leased to DHCP to permitted MAC addresses. Simply adding the IPs to an allowed list doesn't work since someone could steal an active lease once the original client left the network (window between disconnect and lease return-to-pool). A MAC-IP pair helps track who has the lease at a given time (good for auditing), but a database tracking MAC-IP pairs + username at captive portal/proxy login is the best.
Basically, not until a user logs in with a valid mac address and a valid username and gets logged can they access the network. By default all IP addresses are in a blocked ACL and then moved over to a pass ACL when the login process is finished. Storing these MAC-IP pass-OK ACLs is the challenge. While we could statefully [keep-state] reload the firewall ruleset each time we wanted to add a new pass or remove an expired one, that seems pretty expensive. Instead, I'm going to try using in-memory tables.
Maybe next week I'll post more about the entire system (written mostly in perl).