Как раз недавно такое настроил одной сети. При этом были внесены небольшие изменения:
1) в таблице mac_uid поле mac было увеличено до 16 символов - перед маком сохраняется номер вилана.
2) файл радиуса /usr/local/etc/raddb/sql.conf:
authorize_check_query = "call radcheck('%{User-Name}')"
authorize_reply_query = "call radreply('%{User-Name}', '%{Called-Station-Id}')"
postauth_query = "call radupdate('%{User-Name}','%{reply:Framed-IP-Address}',\
'%{Called-Station-Id}', 'nas=%{NAS-IP-Address}')"
accounting_update_query = "call radupdate('%{User-Name}','%{Framed-IP-Address}',\
'%{Called-Station-Id}', 'nas=%{NAS-IP-Address}')"}
микротик в параметре Called-Station-Id присылает имя ... эээ... короче, на каждом вилане настроен dhcp с именем dhcp_номерvlan. Запросы с этого вилана будут идти на радиус, например, так: Called-Station-Id = dhcp_15. Здесь 15 - номер vlan
3) в mysql процедурах я сделал "отрезание" префикса dhcp_ (обратите внимание, что это имя прописано жестко в процедурах) и по оставшемуся числу берем подсетку. Например, для 15 получим 10.0.15.xx
Сами процедуры:
alter table mac_uid change mac `mac` varchar(16) DEFAULT NULL;
DROP FUNCTION IF EXISTS `get_ip_w_net`;
DELIMITER $$
CREATE FUNCTION `get_ip_w_net` (user_id INTEGER UNSIGNED, net INTEGER UNSIGNED)
RETURNS VARCHAR(15) NO SQL
BEGIN
DECLARE user_ip VARCHAR(15);
DECLARE real_ip VARCHAR(15);
SELECT net * 256 INTO net;
SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool
WHERE uid = user_id AND type='static' LIMIT 1;
IF( user_ip IS NOT NULL ) THEN RETURN user_ip; END IF;
UPDATE ip_pool SET uid = user_id, `release` = UNIX_TIMESTAMP() + 300
WHERE id = (SELECT id FROM (
(SELECT id, uid FROM ip_pool
WHERE uid = 0
AND type = 'dynamic'
AND realip = IF(real_ip>0,1,0)
AND ip >= (INET_ATON('10.0.0.0') + net)
AND ip <= (INET_ATON('10.0.0.255') + net)
LIMIT 1)
UNION
(SELECT id, uid FROM ip_pool
WHERE uid = user_id
AND type = 'dynamic'
AND realip = IF(real_ip>0,1,0)
AND ip >= (INET_ATON('10.0.0.0') + net)
AND ip <= (INET_ATON('10.0.0.255') + net)
LIMIT 1)
) AS tbl ORDER BY uid DESC LIMIT 1);
SELECT INET_NTOA(ip) INTO user_ip FROM ip_pool
WHERE uid = user_id
AND ip >= (INET_ATON('10.0.0.0') + net)
AND ip <= (INET_ATON('10.0.0.255') + net)
LIMIT 1;
RETURN user_ip;
END$$
DELIMITER ;
DROP FUNCTION strSplit;
CREATE FUNCTION strSplit(x MEDIUMTEXT, delim MEDIUMTEXT, pos int)
RETURNS MEDIUMTEXT
RETURN
TRIM(BOTH '\r' FROM TRIM(
REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1), delim, '')
));
DROP PROCEDURE IF EXISTS `radreply`;
DELIMITER $$
CREATE PROCEDURE `radreply`(IN login VARCHAR(64), IN net VARCHAR(64))
BEGIN
DECLARE usr_mac VARCHAR(16);
DECLARE usr_ip VARCHAR(15);
DECLARE usr_id INT;
DECLARE usr_state VARCHAR(10);
DECLARE add_attr MEDIUMTEXT;
DECLARE line MEDIUMTEXT;
DECLARE i INT DEFAULT 1;
SELECT REPLACE(net, 'dhcp_', '') INTO net;
SELECT REPLACE(login, ':', '') INTO usr_mac;
SELECT CONCAT(net, usr_mac) INTO usr_mac;
SELECT uid INTO usr_id FROM mac_uid WHERE mac=usr_mac;
IF usr_id IS NOT NULL AND usr_id>0 THEN
SELECT get_ip_w_net(usr_id, net) INTO usr_ip;
UPDATE mac_uid SET ip=0 WHERE ip=INET_ATON(usr_ip) AND uid<>usr_id;
UPDATE mac_uid SET ip=INET_ATON(usr_ip), time=UNIX_TIMESTAMP() WHERE uid=usr_id;
ELSE
UPDATE mac_uid SET ip=0 WHERE time < (UNIX_TIMESTAMP()-3600);
START TRANSACTION;
SELECT INET_NTOA(ip) INTO usr_ip FROM ip_pool p WHERE uid=0 AND type='dynamic'
AND NOT EXISTS (SELECT ip FROM mac_uid WHERE ip=p.ip)
AND ip >= (INET_ATON('10.0.0.0') + net*256)
AND ip <= (INET_ATON('10.0.0.255') + net*256)
ORDER BY RAND() LIMIT 1 FOR UPDATE;
INSERT INTO mac_uid VALUES(
NULL, usr_mac, INET_ATON(usr_ip), 0, UNIX_TIMESTAMP(), 0, 0, 0)
ON DUPLICATE KEY
UPDATE ip=INET_ATON(usr_ip), time=UNIX_TIMESTAMP();
COMMIT;
SELECT INET_NTOA(ip) INTO usr_ip FROM mac_uid WHERE mac=usr_mac;
END IF;
SELECT radius_attr INTO add_attr FROM users_services
WHERE uid=usr_id AND tags LIKE '%,inet,%' LIMIT 1;
SELECT NULL, login, 'Framed-IP-Address', usr_ip, '=';
SELECT NULL, login, 'Session-Timeout', '900', '=';
attr_loop: WHILE TRUE DO
SELECT strSplit(add_attr, '\n', i) INTO line;
IF LENGTH(line) = 0 OR i > 20 THEN LEAVE attr_loop; END IF;
IF line LIKE '%+=%' THEN
SELECT NULL,login,strSplit(line, '+=', 1),strSplit(line, '+=', 2),'+=';
ELSEIF line LIKE '%=%' THEN
SELECT NULL,login,strSplit(line, '=', 1),strSplit(line, '=', 2),'=';
END IF;
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;
DROP PROCEDURE IF EXISTS `radupdate`;
DELIMITER $$
CREATE PROCEDURE `radupdate`(
IN login VARCHAR(64), IN ipa VARCHAR(16), IN net VARCHAR(64), IN properties VARCHAR(255))
BEGIN
DECLARE usr_mac VARCHAR(16);
SELECT REPLACE(login, ':', '') INTO usr_mac;
SELECT REPLACE(net, 'dhcp_', '') INTO net;
CALL set_auth(ipa, CONCAT('mod=dhcp;vlan=', net, ';user=', usr_mac, ';', REPLACE(properties,':','')));
UPDATE mac_uid SET time=UNIX_TIMESTAMP() WHERE ip=INET_ATON(ipa) LIMIT 1;
END$$
DELIMITER ;
Если у вас пул не 10.0.xx.xx, то меняйте INET_ATON('10.0.0.0') + net на, например INET_ATON('192.168.0.0') + net и т.д
P.S. Рекомендую ознакомиться
http://nodeny.com.ua:8080/wiki/index.php/%D0%9C%D0%B8%D0%BA%D1%80%D0%BE%D1%82%D0%B8%D0%BAP.P.S. В процедурах добавлен код из модуля радиус атрибутов - если вам не нужна скорость по радиусу - удалите от attr_loop до END WHILE