UNPKG

domotz-remote-pawn

Version:

Domotz Agent

317 lines (314 loc) 12.7 kB
// Copyright (c) 2011 Andrew Paprocki var assert = require('assert'); var protocol = require('./protocol'); module.exports.parse = function(msg, rinfo) { function trimNulls(str) { var idx = str.indexOf('\u0000'); return (-1 === idx) ? str : str.substr(0, idx); } function readIpRaw(msg, offset) { if (0 === msg.readUInt8(offset)) return undefined; return '' + msg.readUInt8(offset++) + '.' + msg.readUInt8(offset++) + '.' + msg.readUInt8(offset++) + '.' + msg.readUInt8(offset++); } function readIp(msg, offset, obj, name) { var len = msg.readUInt8(offset++); assert.strictEqual(len, 4); obj[name] = readIpRaw(msg, offset); return offset + len; } function readString(msg, offset, obj, name) { var len = msg.readUInt8(offset++); obj[name] = msg.toString('ascii', offset, offset + len); offset += len; return offset; } function readAddressRaw(msg, offset, len) { var addr = ''; while (len-- > 0) { var b = msg.readUInt8(offset++); addr += (b + 0x100).toString(16).substr(-2); if (len > 0) { addr += ':'; } } return addr; } function readHex(msg, offset, obj, name) { var len = msg.readUInt8(offset++); obj[name] = readHexRaw(msg, offset, len); offset += len; return offset; } function readHexRaw(msg, offset, len) { var data = ''; while (len-- > 0) { var b = msg.readUInt8(offset++); data += (b + 0x100).toString(16).substr(-2); } return data; } //console.info(rinfo.address + ':' + rinfo.port + '/' + msg.length + 'b'); var p = { op: protocol.BOOTPMessageType.get(msg.readUInt8(0)), // htype is combined into chaddr field object hlen: msg.readUInt8(2), hops: msg.readUInt8(3), xid: msg.readUInt32BE(4), secs: msg.readUInt16BE(8), flags: msg.readUInt16BE(10), ciaddr: readIpRaw(msg, 12), yiaddr: readIpRaw(msg, 16), siaddr: readIpRaw(msg, 20), giaddr: readIpRaw(msg, 24), chaddr: protocol.createHardwareAddress( protocol.ARPHardwareType.get(msg.readUInt8(1)), readAddressRaw(msg, 28, msg.readUInt8(2))), sname: trimNulls(msg.toString('ascii', 44, 108)), file: trimNulls(msg.toString('ascii', 108, 236)), magic: msg.readUInt32BE(236), options: {} }; var offset = 240; var code = 0; while (code != 255 && offset < msg.length) { code = msg.readUInt8(offset++); switch (code) { case 0: continue; // pad case 255: break; // end case 1: { // subnetMask offset = readIp(msg, offset, p.options, 'subnetMask'); break; } case 2: { // timeOffset var len = msg.readUInt8(offset++); assert.strictEqual(len, 4); p.options.timeOffset = msg.readUInt32BE(offset); offset += len; break; } case 3: { // routerOption var len = msg.readUInt8(offset++); assert.strictEqual(len % 4, 0); p.options.routerOption = []; while (len > 0) { p.options.routerOption.push(readIpRaw(msg, offset)); offset += 4; len -= 4; } break; } case 4: { // timeServerOption var len = msg.readUInt8(offset++); assert.strictEqual(len % 4, 0); p.options.timeServerOption = []; while (len > 0) { p.options.timeServerOption.push(readIpRaw(msg, offset)); offset += 4; len -= 4; } break; } case 6: { // domainNameServerOption var len = msg.readUInt8(offset++); assert.strictEqual(len % 4, 0); p.options.domainNameServerOption = []; while (len > 0) { p.options.domainNameServerOption.push( readIpRaw(msg, offset)); offset += 4; len -= 4; } break; } case 12: { // hostName offset = readString(msg, offset, p.options, 'hostName'); break; } case 15: { // domainName offset = readString(msg, offset, p.options, 'domainName'); break; } case 43: { // vendorOptions var len = msg.readUInt8(offset++); p.options.vendorOptions = {}; while (len > 0) { var vendop = msg.readUInt8(offset++); var vendoplen = msg.readUInt8(offset++); var buf = new Buffer(vendoplen); msg.copy(buf, 0, offset, offset + vendoplen); p.options.vendorOptions[vendop] = buf; len -= 2 + vendoplen; offset += vendoplen; } break; } case 50: { // requestedIpAddress offset = readIp(msg, offset, p.options, 'requestedIpAddress'); break; } case 51: { // ipAddressLeaseTime var len = msg.readUInt8(offset++); assert.strictEqual(len, 4); p.options.ipAddressLeaseTime = msg.readUInt32BE(offset); offset += 4; break; } case 52: { // optionOverload var len = msg.readUInt8(offset++); assert.strictEqual(len, 1); p.options.optionOverload = msg.readUInt8(offset++); break; } case 53: { // dhcpMessageType var len = msg.readUInt8(offset++); assert.strictEqual(len, 1); var mtype = msg.readUInt8(offset++); assert.ok(1 <= mtype); assert.ok(8 >= mtype); p.options.dhcpMessageType = protocol.DHCPMessageType.get(mtype); break; } case 54: { // serverIdentifier offset = readIp(msg, offset, p.options, 'serverIdentifier'); break; } case 55: { // parameterRequestList var len = msg.readUInt8(offset++); p.options.parameterRequestList = []; while (len-- > 0) { var option = msg.readUInt8(offset++); p.options.parameterRequestList.push(option); } break; } case 57: { // maximumMessageSize var len = msg.readUInt8(offset++); assert.strictEqual(len, 2); p.options.maximumMessageSize = msg.readUInt16BE(offset); offset += len; break; } case 58: { // renewalTimeValue var len = msg.readUInt8(offset++); assert.strictEqual(len, 4); p.options.renewalTimeValue = msg.readUInt32BE(offset); offset += len; break; } case 59: { // rebindingTimeValue var len = msg.readUInt8(offset++); assert.strictEqual(len, 4); p.options.rebindingTimeValue = msg.readUInt32BE(offset); offset += len; break; } case 60: { // vendorClassIdentifier offset = readString(msg, offset, p.options, 'vendorClassIdentifier'); break; } case 61: { // clientIdentifier var len = msg.readUInt8(offset++); p.options.clientIdentifier = protocol.createHardwareAddress( protocol.ARPHardwareType.get(msg.readUInt8(offset)), readAddressRaw(msg, offset + 1, len - 1)); offset += len; break; } case 72: { // defaultWWWServers var len = msg.readUInt8(offset++); assert.strictEqual(len % 4, 0); p.options.deafultWWWSevers = []; while (len > 0) { p.options.deafultWWWSevers.push(readIpRaw(msg, offset)); offset += 4; len -= 4; } break; } case 81: { // fullyQualifiedDomainName var len = msg.readUInt8(offset++); p.options.fullyQualifiedDomainName = { flags: msg.readUInt8(offset), name: msg.toString('ascii', offset + 3, offset + len) }; offset += len; break; } case 82: { // relayAgentInformation (RFC 3046) var len = msg.readUInt8(offset++); p.options.relayAgentInformation = {}; var cur = offset; offset += len; while (cur < offset) { var subopt = msg.readUInt8(cur++); switch (subopt) { case 1: { // agentCircuitId (RFC 3046) cur = readHex(msg, cur, p.options.relayAgentInformation, 'agentCircuitId'); break; } case 2: { // agentRemoteId (RFC 3046) cur = readHex(msg, cur, p.options.relayAgentInformation, 'agentRemoteId'); break; } case 4: { // docsisDeviceClass (RFC 3256) var sublen = msg.readUInt8(cur++); assert.strictEqual(sublen, 4); p.options.relayAgentInformation.docsisDeviceClass = msg.readUInt32(cur); cur += sublen; break; } case 5: { // linkSelection (RFC 3527) assert.strictEqual(sublen, 4); cur = readIp(msg, cur, p.options.relayAgentInformation, 'linkSelectionSubnet'); break; } case 6: { // subscriberId (RFC 3993) cur = readString(msg, cur, p.options.relayAgentInformation, 'subscriberId'); break; } default: { console.info('Unhandled DHCP option 82 sub-option ' + subopt + ", len " + sublen); var sublen = msg.readUInt8(cur++); cur += sublen; break; } } } break; } case 118: { // subnetSelection offset = readIp(msg, offset, p.options, 'subnetAddress'); break; } case 252: { // The Web Proxy Auto Discovery (WPAD) offset = readString(msg, offset, p.options, 'wpadUrl'); break; } default: { var len = msg.readUInt8(offset++); console.info('Unhandled DHCP option ' + code + '/' + len + 'b'); offset += len; break; } } } return p; };