diff --git a/lib/radius.js b/lib/radius.js index 655c15b..803e427 100644 --- a/lib/radius.js +++ b/lib/radius.js @@ -2,6 +2,8 @@ var fs = require("fs"); var util = require("util"); var crypto = require("crypto"); var path = require("path"); +var net = require("net"); +var v6 = require('ip-address').v6; var Radius = {}; @@ -485,6 +487,19 @@ Radius.decode_attributes = function(data, attr_hash, vendor, raw_attrs) { } value = octets.join("."); break; + case "ipv6prefix": + var prefix = value.readUInt8(1); + var octets = []; + for (var i = 1; i < value.length/2; i++) { + octets.push(parseInt(value.readUInt16BE(i*2)).toString(16)); + } + value = octets.join(':')+'/'+prefix; + var addr = new v6.Address(octets.join(':')); + if (!addr.isValid()) { + throw new Error("IPv6 prefix is not valid"); + } + value = addr.correctForm()+'/'+prefix; + break; case "date": value = new Date(value.readUInt32BE(0) * 1000); break; @@ -814,6 +829,26 @@ Radius.encode_attributes = function(packet, attributes, vendor) { throw new Error("encode: invalid IP: " + in_value); } break; + case "ipv6prefix": + // rfc3162 + // reserved (1 byte) / prefix-length (1 byte) / prefix (16 bytes) + out_value = new Buffer(18); + out_value.fill(0); + var addr = in_value.split('/'); + if (addr.length != 2) { + throw new Error("encode: invalid IPv6 prefix, no /"); + } + if (!net.isIPv6(addr[0])) { + throw new Error("encode: invalid IPv6 prefix"); + } + var prefix = addr[1].slice(1); + out_value.writeUInt8(64, 1); + addrs = addr[0].split(':'); + for (var j = 0; j < addrs.length; j++) { + if (addrs[j] != '') + out_value.writeUInt16BE(parseInt(addrs[j], 16), j*2+2); + } + break; case "date": in_value = Math.floor(in_value.getTime() / 1000); case "time": diff --git a/package.json b/package.json index b8056c2..72233a0 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,14 @@ }, "engines": { "node": ">=0.8.0" }, "devDependencies": { - "nodeunit": "~0.8.6" + "nodeunit": "~0.8.6", + "ip-address": "*" }, "scripts": { "test": "nodeunit test" }, - "keywords": ["radius"] + "keywords": ["radius"], + "dependencies": { + "ip-address": "*" + } } diff --git a/test/radius.test.js b/test/radius.test.js index 7ef0267..8316fe8 100755 --- a/test/radius.test.js +++ b/test/radius.test.js @@ -928,6 +928,36 @@ module.exports = testCase({ "User-Password": "降龙十八掌" }, decoded.attributes ); + test.done(); + }, + + test_ipv6prefix_encode: function(test) { + var decoded = radius.decode({ + packet: radius.encode({ + code: 'Access-Request', + authenticator: new Buffer('426edca213c1bf6e005e90a64105ca3a', 'hex'), + attributes: [['Framed-IPv6-Prefix', '2a05:4680:4::/64']], + secret: secret + }), + secret: secret + }); + + test.equal( decoded.attributes['Framed-IPv6-Prefix'], '2a05:4680:4::/64' ); + + // bad ipv6prefix + test.throws(function() { + var decoded = radius.decode({ + packet: radius.encode({ + code: 'Access-Request', + authenticator: new Buffer('426edca213c1bf6e005e90a64105ca3a', 'hex'), + attributes: [['Framed-IPv6-Prefix', new Buffer('00402')]], + secret: secret + }), + secret: secret + }); + }); + test.done(); } + });