Skip to content

Commit

Permalink
Add refactor and test ipv6 header extensions
Browse files Browse the repository at this point in the history
  -  Use same decoder table for both ipv4 and ipv6

  -  Introduce _error concept on NoNext. This maybe
     the way all decode errors are communicated from
     now on.

  - Add tests for ipv6
  • Loading branch information
jmaxxz committed Mar 11, 2015
1 parent ea0d997 commit 3f846ba
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 12 deletions.
32 changes: 20 additions & 12 deletions decode/ip_protocols.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
var protocols = new Array(256);
// declare export early to avoid circular dependancy chains
module.exports = protocols;


var IpV6HeaderExtension = require("./ipv6headers/header_extension");

//https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
function init(){
protocols[0] =
protocols[1] = require("./icmp");
protocols[2] = require("./igmp");
protocols[4] = require("./ipv4");
protocols[6] = require("./tcp");
protocols[17] = require("./udp");
protocols[41] = require("./ipv6");
protocols[59] = function NoNext(){}; //No next ipv6

protocols[0] = IpV6HeaderExtension;
protocols[1] = require("./icmp");
protocols[2] = require("./igmp");
protocols[4] = require("./ipv4");
protocols[6] = require("./tcp");
protocols[17] = require("./udp");
protocols[41] = require("./ipv6");
protocols[43] = IpV6HeaderExtension;
protocols[51] = IpV6HeaderExtension;
protocols[59] = require("./ipv6headers/no_next");
protocols[60] = IpV6HeaderExtension;
protocols[135] = IpV6HeaderExtension;
protocols[139] = IpV6HeaderExtension;
protocols[140] = IpV6HeaderExtension;
}
init();

module.exports = protocols;
init();
34 changes: 34 additions & 0 deletions decode/ipv6headers/header_extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
var protocols = require("../ip_protocols");

// A generic header extension class
// https://tools.ietf.org/html/rfc6564
// none of the header specif details will
// be decoded by this extension.
function HeaderExtension() {
this.payload = undefined;
this.nextHeader = undefined;
this.headerLength = undefined;
}

HeaderExtension.prototype.decode = function (raw_packet, offset) {
var originalOffset = offset;
this.nextHeader = raw_packet[offset++];
this.headerLength = (raw_packet[offset++]+1)*8;

offset = originalOffset + this.headerLength;

var ProtocolDecoder = protocols[this.nextHeader];
if(ProtocolDecoder === undefined) {
this.protocolName = "Unknown";
} else {
this.payload = new ProtocolDecoder().decode(raw_packet, offset, raw_packet.length - offset);
}

return this;
};

HeaderExtension.prototype.toString = function () {
return "";
};

module.exports = HeaderExtension;
20 changes: 20 additions & 0 deletions decode/ipv6headers/no_next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function NoNext() {
this._error = undefined;
}

// The no next header is nothing. Just an empty payload.
NoNext.prototype.decode = function (raw_packet, offset) {
var remainingLength = raw_packet.length - offset;
if(remainingLength !== 0) {
this._error = "There is more packet left to be parse," +
"but NoNext.decode was called with " + remainingLength +
" bytes left.";
}
return this;
};

NoNext.prototype.toString = function () {
return "";
};

module.exports = NoNext;
48 changes: 48 additions & 0 deletions spec/ipv6headers/header_extension.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var HeaderExtension = require("../../decode/ipv6headers/header_extension");
var NoNext = require("../../decode/ipv6headers/no_next");
var should = require("should");

describe("HeaderExtension", function(){
var instance, example;
beforeEach(function(){
instance = new HeaderExtension();
example = new Buffer("3B" + // No next will be the next header
"01" + // the length of the the header in 8 byte units - 8bytes
"0000000000000000" +
"000000000000", // details about the current header
"hex");
});

describe("#decode()", function(){
it("is a function", function(){
instance.decode.should.be.type("function");
});

it("sets #nextHeader to the protocol number of the next payload", function(){
instance.decode(example, 0);
instance.should.have.property("nextHeader", 0x3B);
});

it("sets #headerLength to the length of the header in bytes", function(){
instance.decode(example, 0);
instance.should.have.property("headerLength", 16);
});

it("sets #payload to the next header", function(){
instance.decode(example, 0);
instance.payload.should.be.instanceOf(NoNext);
should.not.exist(instance.payload._error);
});
});

describe("#toString()", function(){
it("is a function", function(){
instance.toString.should.be.type("function");
});

it("decodes nothing", function(){
instance.decode(example, 0);
instance.toString().should.be.exactly("");
});
});
});
33 changes: 33 additions & 0 deletions spec/ipv6headers/no_next.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var NoNext = require("../../decode/ipv6headers/no_next");
var should = require("should");

describe("NoNext", function(){
var instance, example;
beforeEach(function(){
instance = new NoNext();
example = new Buffer("", "hex");
});

describe("#decode()", function(){
it("is a function", function(){
instance.decode.should.be.type("function");
});

it("decodes nothing", function(){
instance.decode(example, 0);
should.not.exist(instance._error);
});

it("sets #_error is something is wrong", function(){
//should not have data left
instance.decode(new Buffer("00", "hex"), 0);
should.exist(instance._error);
});
});

describe("#toString()", function(){
it("is a function", function(){
instance.toString.should.be.type("function");
});
});
});

0 comments on commit 3f846ba

Please sign in to comment.