diff --git a/examples/server.js b/examples/server.js index 9820d70..a6d0c3b 100644 --- a/examples/server.js +++ b/examples/server.js @@ -37,7 +37,19 @@ var s = dhcpd.createServer({ } else { return 'x64linux.0'; } - } + }, + + // Allocate an ip based on a static Option82 Circuit-ID binding + // relayAgentInformation: { + // "fa0/1": "192.168.3.101" + // }, + // Allocate an ip based on a callback function + // relayAgentInformation: function() { + // return function(remoteId, circuitId) { + // if (remoteId == "als01" && circuitId == "fa0/1") + // return "192.168.3.102"; + // } + // }, }); s.on('message', function(data) { diff --git a/lib/dhcp.js b/lib/dhcp.js index e009e81..94f34f6 100644 --- a/lib/dhcp.js +++ b/lib/dhcp.js @@ -288,6 +288,19 @@ Server.prototype = { return _static[clientMAC]; } + + // Is there a option82 binding? + const _relayAgentInformation = this.config('relayAgentInformation'); + console.log("Option82: %s", typeof _relayAgentInformation[req.options["82"]["remoteId"]]); + if (typeof _relayAgentInformation === "function") { + const relayAgentInformationResult = _relayAgentInformation(req.options["82"]["remoteId"], req.options["82"]["circuitId"]); + if (relayAgentInformationResult) + return relayAgentInformationResult; + } else if (typeof _relayAgentInformation[req.options["82"]["remoteId"]] === "string") { + return _relayAgentInformation[req.options["82"]["circuitId"]]; + } else if (typeof _relayAgentInformation[req.options["82"]["remoteId"]] === "object") { + return _relayAgentInformation[req.options["82"]["remoteId"][req.options["82"]["circuitId"]]]; + } const randIP = this.config('randomIP'); const _tmp = this.config('range'); diff --git a/lib/options.js b/lib/options.js index b5f597a..509164e 100644 --- a/lib/options.js +++ b/lib/options.js @@ -459,10 +459,14 @@ const opts = { name: 'Rapid Commit', type: 'Bool', attr: 'rapidCommit' - }, /* - 82: { // RFC 3046, relayAgentInformation - - },*/ + }, + 82: { // TODO: Add support for more vendors + // RFC 3046, relayAgentInformation + name: "Relay Agent Information", + type: "SubOptions", + config: "relayAgentInformation", + vendor: "cisco" + }, 95: { name: 'LDAP Servers', type: 'IPs', diff --git a/lib/seqbuffer.js b/lib/seqbuffer.js index 3eb3547..a0cf2de 100644 --- a/lib/seqbuffer.js +++ b/lib/seqbuffer.js @@ -278,7 +278,11 @@ SeqBuffer.prototype = { let len = this.getUInt8(); if (opt in Options) { - options[opt] = this['get' + Options[opt].type](len); + if (opt == 82) { + options[opt] = this['get' + Options[opt].type](Options[opt].vendor); + } else { + options[opt] = this['get' + Options[opt].type](len); + } } else { this._r += len; console.error('Option ' + opt + ' not known'); @@ -287,6 +291,41 @@ SeqBuffer.prototype = { } return options; }, + getSubOptions(vendor) { + + const sub_options = {}; + const buf = this._data; + + while (this._r < buf.length - 1) { + let opt = this.getUInt8(); + let len = this.getUInt8(); + + // Agent Circuit ID Sub-option + if (opt == 0x01) { + switch(vendor) { + default: + sub_options["circuitId"] = this.getASCII(len); + } + } + + // Agent Remote ID Sub-option + if (opt == 0x02) { + switch(vendor) { + case "cisco": + // Cisco Remote ID Type + let sub_type = this.getUInt8(); + // Cisco Remote ID Length + let sub_type_length = this.getUInt8(); + sub_options["remoteId"] = this.getASCII(sub_type_length); + break; + default: + sub_options["remoteId"] = this.getASCII(len); + break; + } + } + } + return sub_options; + }, // addUInt8s: function(arr) { diff --git a/tests/segbuffer.test.js b/tests/segbuffer.test.js index 0f58852..fec519e 100644 --- a/tests/segbuffer.test.js +++ b/tests/segbuffer.test.js @@ -429,4 +429,19 @@ describe('Segbuffer', function() { }); + it('should get option82 sub-options correctly for vendor cisco', function() { + + var vendor = "cisco"; + + // Option82 with Sub-Option 1 first + var sb_1 = new SeqBuffer(new Buffer([0x52, 0x19, 0x01, 0x0a, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x5f, 0x49, 0x44, 0x02, 0x0b, 0x01, 0x09, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x49, 0x44])); + + sb_1.getSubOptions(vendor).should.be.deepEqual({ circuitId: 'CIRCUIT_ID', remoteId: 'REMOTE_ID' }); + + // Option82 with Sub-Option 2 first + var sb_2 = new SeqBuffer(new Buffer([0x52, 0x19, 0x02, 0x0b, 0x01, 0x09, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x49, 0x44, 0x01, 0x0a, 0x43, 0x49, 0x52, 0x43, 0x55, 0x49, 0x54, 0x5f, 0x49, 0x44])); + + sb_2.getSubOptions(vendor).should.be.deepEqual({ circuitId: 'CIRCUIT_ID', remoteId: 'REMOTE_ID' }); + }); + });