Comparing version 2.0.1 to 2.1.0
var EthernetAddr = require("./ethernet_addr"); | ||
var IPv4Addr = require("./ipv4_addr"); | ||
function Arp() { | ||
this.htype = null; | ||
this.ptype = null; | ||
this.heln = null; | ||
this.plen = null; | ||
this.operation = null; | ||
this.sender_ha = null; | ||
this.sender_pa = null; | ||
this.target_ha = null; | ||
this.target_pa = null; | ||
function Arp(emitter) { | ||
this.emitter = emitter; | ||
this.htype = undefined; | ||
this.ptype = undefined; | ||
this.hlen = undefined; | ||
this.plen = undefined; | ||
this.operation = undefined; | ||
this.sender_ha = undefined; | ||
this.sender_pa = undefined; | ||
this.target_ha = undefined; | ||
this.target_pa = undefined; | ||
} | ||
@@ -25,11 +26,15 @@ | ||
this.sender_ha = new EthernetAddr(raw_packet, offset + 8); // 8, 9, 10, 11, 12, 13 | ||
this.sender_pa = new IPv4Addr(raw_packet, offset + 14); // 14, 15, 16, 17 | ||
this.sender_pa = new IPv4Addr().decode(raw_packet, offset + 14); // 14, 15, 16, 17 | ||
this.target_ha = new EthernetAddr(raw_packet, offset + 18); // 18, 19, 20, 21, 22, 23 | ||
this.target_pa = new IPv4Addr(raw_packet, offset + 24); // 24, 25, 26, 27 | ||
this.target_pa = new IPv4Addr().decode(raw_packet, offset + 24); // 24, 25, 26, 27 | ||
} | ||
// don't know how to decode more exotic ARP types yet, but please add them | ||
if(this.emitter) { this.emitter.emit("arp", this); } | ||
return this; | ||
}; | ||
Arp.prototype.decoderName = "arp"; | ||
Arp.prototype.eventsOnDecode = true; | ||
Arp.prototype.toString = function () { | ||
@@ -36,0 +41,0 @@ var ret = ""; |
var IPv4Addr = require("./ipv4_addr"); | ||
var IPv6Addr = require("./ipv6_addr"); | ||
function DNSHeader(raw_packet, offset) { | ||
this.id = raw_packet.readUInt16BE(offset); // 0, 1 | ||
this.qr = (raw_packet[offset + 2] & 128) >> 7; | ||
this.opcode = (raw_packet[offset + 2] & 120) >> 3; | ||
this.aa = (raw_packet[offset + 2] & 4) >> 2; | ||
this.tc = (raw_packet[offset + 2] & 2) >> 1; | ||
this.rd = raw_packet[offset + 2] & 1; | ||
this.ra = (raw_packet[offset + 3] & 128) >> 7; | ||
this.z = 0; // spec says this MUST always be 0 | ||
this.rcode = raw_packet[offset + 3] & 15; | ||
this.qdcount = raw_packet.readUInt16BE(offset + 4); // 4, 5 | ||
this.ancount = raw_packet.readUInt16BE(offset + 6); // 6, 7 | ||
this.nscount = raw_packet.readUInt16BE(offset + 8); // 8, 9 | ||
this.arcount = raw_packet.readUInt16BE(offset + 10); // 10, 11 | ||
function DnsFlags() { | ||
// is this a response? | ||
this.isResponse = undefined; | ||
// 0 == Query | ||
// 1 == Inverse query | ||
// 2 == Status | ||
// 3-15 Reserved for future use | ||
this.opcode = undefined; | ||
// is the server the authority for the domain? | ||
this.isAuthority = undefined; | ||
// is this message truncated? | ||
this.isTruncated = undefined; | ||
// should name server recursively | ||
// resolve domain? | ||
this.isRecursionDesired = undefined; | ||
// Can the server even do recursion? | ||
this.isRecursionAvailible = undefined; | ||
// Reserved for future use, unless the present is the future | ||
// then assume the past is the present and the present is the | ||
// past...or just update to support whatever this became. | ||
// | ||
// currently "should" always be zero. | ||
this.z = undefined; | ||
// 0 == no error | ||
// 1 == format error (query could not be interpeted) | ||
// 2 == server error | ||
// 3 == name error (domain requested by query does not exist) | ||
// 4 == unsupported request | ||
// 5 == refused | ||
// a 4bit reply status code | ||
this.responseCode = undefined; | ||
} | ||
DNSHeader.prototype.toString = function () { | ||
return "{" + | ||
" id:" + this.id + | ||
" qr:" + this.qr + | ||
" op:" + this.opcode + | ||
" aa:" + this.aa + | ||
" tc:" + this.tc + | ||
" rd:" + this.rd + | ||
" ra:" + this.ra + | ||
" rc:" + this.rcode + | ||
" qd:" + this.qdcount + | ||
" an:" + this.ancount + | ||
" ns:" + this.nscount + | ||
" ar:" + this.arcount + | ||
DnsFlags.prototype.decode = function (raw_packet, offset) { | ||
var byte1 = raw_packet[offset]; | ||
var byte2 = raw_packet[offset + 1]; | ||
this.isResponse = Boolean(byte1 & 0x80); | ||
this.opcode = (byte1 & 0x78) >> 3; | ||
this.isAuthority = Boolean(byte1 & 0x04); | ||
this.isTruncated = Boolean(byte1 & 0x02); | ||
this.isRecursionDesired = Boolean(byte1 & 0x01); | ||
this.isRecursionAvailible = Boolean(byte2 & 0x80); | ||
this.z = byte2 & 0x70 >> 4; | ||
this.responseCode = byte2 & 0x0F; | ||
return this; | ||
}; | ||
DnsFlags.prototype.toString = function () { | ||
return "{ isResponse:" + this.isResponse + | ||
" opcode:" + this.opcode + | ||
" isAuthority:" + this.isAuthority + | ||
" isTruncated:" + this.isTruncated + | ||
" isRecursionDesired:" + this.isRecursionDesired + | ||
" isRecursionAvailible:" + this.isRecursionAvailible + | ||
" z:" + this.z + | ||
" responseCode:" + this.responseCode + | ||
" }"; | ||
}; | ||
function DNS() { | ||
this.header = null; | ||
this.question = null; | ||
this.answer = null; | ||
this.authority = null; | ||
this.additional = null; | ||
// not part of DNS, but handy so we don't have to pass these around all over the place | ||
this.raw_packet = null; | ||
this.offset = null; | ||
this.packet_start = null; | ||
this.packet_len = null; | ||
function DNS(emitter) { | ||
this.emitter = emitter; | ||
this.header = undefined; | ||
this.question = undefined; | ||
this.answer = undefined; | ||
this.authority = undefined; | ||
this.additional = undefined; | ||
this._error = undefined; | ||
} | ||
@@ -59,17 +90,25 @@ | ||
DNS.prototype.decoderName = "dns"; | ||
DNS.prototype.eventsOnDecode = true; | ||
// http://tools.ietf.org/html/rfc1035 | ||
DNS.prototype.decode = function (raw_packet, offset, caplen) { | ||
DNS.prototype.decode = function (raw_packet, offset) { | ||
//these 2 fields will be deleted soon. | ||
this.raw_packet = raw_packet; | ||
this.packet_start = offset; | ||
this.offset = offset; | ||
this.packet_len = caplen; | ||
this.header = new DNSHeader(raw_packet, this.offset); | ||
this.id = raw_packet.readUInt16BE(offset); // 0, 1 | ||
this.header = new DnsFlags().decode(raw_packet.readUInt16BE(this.offset+2)); | ||
this.qdcount = raw_packet.readUInt16BE(offset + 4); // 4, 5 | ||
this.ancount = raw_packet.readUInt16BE(offset + 6); // 6, 7 | ||
this.nscount = raw_packet.readUInt16BE(offset + 8); // 8, 9 | ||
this.arcount = raw_packet.readUInt16BE(offset + 10); // 10, 11 | ||
this.offset += 12; | ||
this.question = this.decode_RRs(this.header.qdcount, true); | ||
this.answer = this.decode_RRs(this.header.ancount, false); | ||
this.authority = this.decode_RRs(this.header.nscount, false); | ||
this.additional = this.decode_RRs(this.header.arcount, false); | ||
this.question = this.decode_RRs(this.qdcount, true); | ||
this.answer = this.decode_RRs(this.ancount, false); | ||
this.authority = this.decode_RRs(this.nscount, false); | ||
this.additional = this.decode_RRs(this.arcount, false); | ||
if(this.emitter) { this.emitter.emit("dns", this); } | ||
return this; | ||
@@ -80,3 +119,4 @@ }; | ||
if (count > 100) { | ||
throw new Error("Malformed DNS packet: too many RRs at offset " + this.offset); | ||
this._error = "Malformed DNS packet: too many RRs at offset " + this.offset; | ||
return; | ||
} | ||
@@ -136,4 +176,4 @@ | ||
pos++; | ||
for (var i = pos; i < (pos + len_or_ptr) && i < this.packet_len ; i++) { | ||
if (i > this.packet_len) { | ||
for (var i = pos; i < (pos + len_or_ptr) && i < this.raw_packet.length; i++) { | ||
if (i > this.raw_packet.length) { | ||
throw new Error("invalid DNS RR: read beyond end of packet at offset " + i); | ||
@@ -160,4 +200,4 @@ } | ||
DNS.prototype.decode_RR = function (is_question) { | ||
if (this.offset > this.packet_len) { | ||
throw new Error("Malformed DNS RR. Offset is beyond packet len (decode_RR) :" + this.offset + " packet_len:" + this.packet_len); | ||
if (this.offset > this.raw_packet.length) { | ||
throw new Error("Malformed DNS RR. Offset is beyond packet len (decode_RR) :" + this.offset + " packet_len:" + this.raw_packet.length); | ||
} | ||
@@ -183,3 +223,3 @@ | ||
if (rr.type === 1 && rr.class === 1 && rr.rdlength) { // A, IN | ||
rr.rdata = new IPv4Addr(this.raw_packet, this.offset); | ||
rr.rdata = new IPv4Addr().decode(this.raw_packet, this.offset); | ||
} else if (rr.type === 2 && rr.class === 1) { // NS, IN | ||
@@ -202,12 +242,12 @@ rr.rdata = this.read_name(); | ||
ret += this.header.toString(); | ||
if (this.header.qdcount > 0) { | ||
if (this.qdcount > 0) { | ||
ret += "\n question:" + this.question.rrs[0]; | ||
} | ||
if (this.header.ancount > 0) { | ||
if (this.ancount > 0) { | ||
ret += "\n answer:" + this.answer; | ||
} | ||
if (this.header.nscount > 0) { | ||
if (this.nscount > 0) { | ||
ret += "\n authority:" + this.authority; | ||
} | ||
if (this.header.arcount > 0) { | ||
if (this.arcount > 0) { | ||
ret += "\n additional:" + this.additional; | ||
@@ -214,0 +254,0 @@ } |
var util = require("../util"); | ||
//Also known as MAC address | ||
function EthernetAddr(raw_packet, offset) { | ||
@@ -13,3 +14,3 @@ this.addr = new Array(6); | ||
EthernetAddr.prototype.toString = function () { | ||
EthernetAddr.prototype.toString = function toString() { | ||
return util.int8_to_hex[this.addr[0]] + ":" + | ||
@@ -16,0 +17,0 @@ util.int8_to_hex[this.addr[1]] + ":" + |
@@ -7,3 +7,4 @@ var EthernetAddr = require("./ethernet_addr"); | ||
function EthernetPacket() { | ||
function EthernetPacket(emitter) { | ||
this.emitter = emitter; | ||
this.dhost = null; | ||
@@ -40,9 +41,9 @@ this.shost = null; | ||
case 0x800: // IPv4 | ||
this.payload = new IPv4().decode(raw_packet, offset); | ||
this.payload = new IPv4(this.emitter).decode(raw_packet, offset); | ||
break; | ||
case 0x806: // ARP | ||
this.payload = new Arp().decode(raw_packet, offset); | ||
this.payload = new Arp(this.emitter).decode(raw_packet, offset); | ||
break; | ||
case 0x86dd: // IPv6 - http://en.wikipedia.org/wiki/IPv6 | ||
this.payload = new IPv6().decode(raw_packet, offset); | ||
this.payload = new IPv6(this.emitter).decode(raw_packet, offset); | ||
break; | ||
@@ -60,2 +61,5 @@ case 0x88cc: // LLDP - http://en.wikipedia.org/wiki/Link_Layer_Discovery_Protocol | ||
EthernetPacket.prototype.decoderName = "ethernet-packet"; | ||
EthernetPacket.prototype.eventsOnDecode = false; | ||
EthernetPacket.prototype.toString = function () { | ||
@@ -62,0 +66,0 @@ var ret = this.shost + " -> " + this.dhost; |
@@ -1,7 +0,6 @@ | ||
function ICMP() { | ||
this.type = null; | ||
this.code = null; | ||
this.checksum = null; | ||
this.id = null; | ||
this.sequence = null; | ||
function ICMP(emitter) { | ||
this.emitter = emitter; | ||
this.type = undefined; | ||
this.code = undefined; | ||
this.checksum = undefined; | ||
} | ||
@@ -11,11 +10,13 @@ | ||
ICMP.prototype.decode = function (raw_packet, offset) { | ||
this.type = raw_packet[offset]; | ||
this.code = raw_packet[offset + 1]; | ||
this.checksum = raw_packet.readUInt16BE(offset + 2); // 2, 3 | ||
this.id = raw_packet.readUInt16BE(offset + 4); // 4, 5 | ||
this.sequence = raw_packet.readUInt16BE(offset + 6); // 6, 7 | ||
this.type = raw_packet[offset++]; | ||
this.code = raw_packet[offset++]; | ||
this.checksum = raw_packet.readUInt16BE(offset); // 2, 3 | ||
if(this.emitter) { this.emitter.emit("icmp", this); } | ||
return this; | ||
}; | ||
ICMP.prototype.decoderName = "icmp"; | ||
ICMP.prototype.eventsOnDecode = true; | ||
ICMP.prototype.toString = function () { | ||
@@ -28,6 +29,2 @@ var ret = ""; | ||
break; | ||
case 1: | ||
case 2: | ||
ret += "Reserved"; | ||
break; | ||
case 3: // destination unreachable | ||
@@ -85,3 +82,3 @@ switch (this.code) { | ||
case 5: // redirect | ||
switch (ret.code) { | ||
switch (this.code) { | ||
case 0: | ||
@@ -100,3 +97,3 @@ ret += "Redirect Network"; | ||
default: | ||
ret += "Redirect (unknown code " + ret.code + ")"; | ||
ret += "Redirect (unknown code " + this.code + ")"; | ||
break; | ||
@@ -103,0 +100,0 @@ } |
@@ -1,21 +0,32 @@ | ||
function IGMP() { | ||
this.type = null; | ||
this.version = null; | ||
this.max_response_time = null; | ||
this.checksum = null; | ||
this.group_address = null; | ||
var IPv4Addr = require("./ipv4_addr"); | ||
function IGMP(emitter) { | ||
this.emitter = emitter; | ||
this.type = undefined; | ||
this.version = undefined; | ||
this.maxResponseTime = undefined; | ||
this.checksum = undefined; | ||
this.groupAddress = undefined; | ||
} | ||
var IPV4Addr = require("./ipv4_addr"); | ||
// http://en.wikipedia.org/wiki/Internet_Group_Management_Protocol | ||
// This is an implementation of V3 | ||
// https://tools.ietf.org/html/rfc3376 | ||
IGMP.prototype.decode = function (raw_packet, offset) { | ||
this.type = raw_packet[offset]; | ||
this.max_response_time = raw_packet[offset + 1]; | ||
// units are 1/10s | ||
// if value < 128 this is an int, else it is a float | ||
// right now we don't handle the float version | ||
this.maxResponseTime =raw_packet[offset + 1]; | ||
this.checksum = raw_packet.readUInt16BE(offset + 2); // 2, 3 | ||
this.group_address = new IPV4Addr(raw_packet, offset + 4); // 4, 5, 6, 7 | ||
this.groupAddress = new IPv4Addr().decode(raw_packet, offset + 4); // 4, 5, 6, 7 | ||
//Membership Query (0x11) | ||
//Membership Report (IGMPv1: 0x12, IGMPv2: 0x16, IGMPv3: 0x22) | ||
//Leave Group (0x17) | ||
switch (this.type) { | ||
case 0x11: | ||
this.version = this.max_response_time > 0 ? 2 : 1; | ||
this.version = 3; | ||
break; | ||
@@ -26,4 +37,2 @@ case 0x12: | ||
case 0x16: | ||
this.version = 2; | ||
break; | ||
case 0x17: | ||
@@ -35,9 +44,11 @@ this.version = 2; | ||
break; | ||
default: | ||
break; | ||
} | ||
if(this.emitter) { this.emitter.emit("igmp", this); } | ||
return this; | ||
}; | ||
IGMP.prototype.decoderName = "igmp"; | ||
IGMP.prototype.eventsOnDecode = true; | ||
IGMP.prototype.toString = function () { | ||
@@ -44,0 +55,0 @@ var ret; |
@@ -10,4 +10,4 @@ // convert binary capture data into objects with friendly names | ||
function decode(packet) { | ||
return new PcapPacket().decode(packet); | ||
function decode(packet, emitter) { | ||
return new PcapPacket(emitter).decode(packet); | ||
} | ||
@@ -14,0 +14,0 @@ |
@@ -1,15 +0,23 @@ | ||
var map = require("../util").int8_to_dec; | ||
var dec = require("../util").int8_to_dec; | ||
function IPv4Addr(raw_packet, offset) { | ||
this.o1 = raw_packet[offset]; | ||
this.o2 = raw_packet[offset + 1]; | ||
this.o3 = raw_packet[offset + 2]; | ||
this.o4 = raw_packet[offset + 3]; | ||
function IPv4Addr() { | ||
this.addr = new Array(4); | ||
} | ||
IPv4Addr.prototype.decode = function decode(raw_packet, offset) { | ||
this.addr[0] = raw_packet[offset]; | ||
this.addr[1] = raw_packet[offset + 1]; | ||
this.addr[2] = raw_packet[offset + 2]; | ||
this.addr[3] = raw_packet[offset + 3]; | ||
return this; | ||
}; | ||
IPv4Addr.prototype.decoderName = "ipv4-addr"; | ||
IPv4Addr.prototype.eventsOnDecode = false; | ||
// Don't use Array.prototype.join here, because string concat is much faster | ||
IPv4Addr.prototype.toString = function () { | ||
return map[this.o1] + "." + map[this.o2] + "." + map[this.o3] + "." + map[this.o4]; | ||
return dec[this.addr[0]] + "." + dec[this.addr[1]] + "." + dec[this.addr[2]] + "." + dec[this.addr[3]]; | ||
}; | ||
module.exports = IPv4Addr; |
@@ -1,14 +0,19 @@ | ||
var ICMP = require("./icmp"); | ||
var IGMP = require("./igmp"); | ||
var TCP = require("./tcp"); | ||
var UDP = require("./udp"); | ||
var IPv6 = require("./ipv6"); | ||
var IPv4Addr = require("./ipv4_addr"); | ||
var protocols = require("./ip_protocols"); | ||
function IPFlags() { | ||
this.reserved = null; | ||
this.df = null; | ||
this.mf = null; | ||
function IPFlags(emitter) { | ||
this.emitter = emitter; | ||
this.reserved = undefined; | ||
this.doNotFragment = undefined; | ||
this.moreFragments = undefined; | ||
} | ||
IPFlags.prototype.decode = function (raw_flags) { | ||
this.reserved = Boolean((raw_flags & 0x80) >> 7); | ||
this.doNotFragment = Boolean((raw_flags & 0x40) > 0); | ||
this.moreFragments = Boolean((raw_flags & 0x20) > 0); | ||
return this; | ||
}; | ||
IPFlags.prototype.toString = function () { | ||
@@ -19,6 +24,6 @@ var ret = "["; | ||
} | ||
if (this.df) { | ||
if (this.doNotFragment) { | ||
ret += "d"; | ||
} | ||
if (this.mf) { | ||
if (this.moreFragments) { | ||
ret += "m"; | ||
@@ -30,18 +35,18 @@ } | ||
function IPv4() { | ||
this.version = null; | ||
this.header_length = null; | ||
this.header_bytes = null; // not part of packet, but handy | ||
this.diffserv = null; | ||
this.total_length = null; | ||
this.identification = null; | ||
this.flags = new IPFlags(); | ||
this.fragment_offset = null; | ||
this.ttl = null; | ||
this.protocol = null; | ||
this.header_checksum = null; | ||
this.saddr = null; | ||
this.daddr = null; | ||
this.protocol_name = null; | ||
this.payload = null; | ||
function IPv4(emitter) { | ||
this.emitter = emitter; | ||
this.version = undefined; | ||
this.headerLength = undefined; | ||
this.diffserv = undefined; | ||
this.length = undefined; | ||
this.identification = undefined; | ||
this.flags = undefined; | ||
this.fragmentOffset = undefined; | ||
this.ttl = undefined; | ||
this.protocol = undefined; | ||
this.headerChecksum = undefined; | ||
this.saddr = undefined; | ||
this.daddr = undefined; | ||
this.protocolName = undefined; | ||
this.payload = undefined; | ||
} | ||
@@ -53,26 +58,33 @@ | ||
this.version = (raw_packet[offset] & 240) >> 4; // first 4 bits | ||
this.header_length = raw_packet[offset] & 15; // second 4 bits | ||
this.header_bytes = this.header_length * 4; | ||
this.version = (raw_packet[offset] & 0xf0) >> 4; | ||
this.headerLength = (raw_packet[offset] & 0x0f) << 2; | ||
offset += 1; | ||
this.diffserv = raw_packet[offset]; | ||
offset += 1; | ||
this.total_length = raw_packet.readUInt16BE(offset, true); | ||
this.length = raw_packet.readUInt16BE(offset, true); | ||
offset += 2; | ||
this.identification = raw_packet.readUInt16BE(offset, true); | ||
offset += 2; | ||
this.flags.reserved = (raw_packet[offset] & 128) >> 7; | ||
this.flags.df = (raw_packet[offset] & 64) >> 6; | ||
this.flags.mf = (raw_packet[offset] & 32) >> 5; | ||
this.fragment_offset = ((raw_packet[offset] & 31) * 256) + raw_packet[offset + 1]; // 13-bits from 6, 7 | ||
this.flags = new IPFlags().decode(raw_packet[offset]); | ||
// flags only uses the top 3 bits of offset so don't advance yet | ||
this.fragmentOffset = ((raw_packet.readUInt16BE(offset) & 0x1fff) << 3); // 13-bits from 6, 7 | ||
offset += 2; | ||
this.ttl = raw_packet[offset]; | ||
offset += 1; | ||
this.protocol = raw_packet[offset]; | ||
offset += 1; | ||
this.header_checksum = raw_packet.readUInt16BE(offset, true); | ||
this.headerChecksum = raw_packet.readUInt16BE(offset, true); | ||
offset += 2; | ||
this.saddr = new IPv4Addr(raw_packet, offset); | ||
this.saddr = new IPv4Addr(this.emitter).decode(raw_packet, offset); | ||
offset += 4; | ||
this.daddr = new IPv4Addr(raw_packet, offset); | ||
this.daddr = new IPv4Addr(this.emitter).decode(raw_packet, offset); | ||
offset += 4; | ||
@@ -82,60 +94,31 @@ | ||
offset = orig_offset + (this.header_length * 4); | ||
offset = orig_offset + this.headerLength; | ||
switch (this.protocol) { | ||
case 1: | ||
this.payload = new ICMP(); | ||
this.payload.decode(raw_packet, offset); | ||
break; | ||
case 2: | ||
this.payload = new IGMP().decode(raw_packet, offset); | ||
break; | ||
case 4: | ||
this.payload = new IPv4().decode(raw_packet, offset); | ||
break; | ||
case 6: | ||
this.payload = new TCP().decode(raw_packet, offset, this.total_length - this.header_bytes); | ||
break; | ||
case 17: | ||
this.payload = new UDP().decode(raw_packet, offset); | ||
break; | ||
case 41: | ||
this.payload = new IPv6().decode(raw_packet, offset); | ||
break; | ||
default: | ||
this.protocol_name = "Unknown"; | ||
var ProtocolDecoder = protocols[this.protocol]; | ||
if(ProtocolDecoder === undefined) { | ||
this.protocolName = "Unknown"; | ||
} else { | ||
this.payload = new ProtocolDecoder(this.emitter).decode(raw_packet, offset, this.length - this.headerLength); | ||
} | ||
if(this.emitter) { this.emitter.emit("ipv4", this); } | ||
return this; | ||
}; | ||
IPv4.prototype.decoderName = "ipv4"; | ||
IPv4.prototype.eventsOnDecode = true; | ||
IPv4.prototype.toString = function () { | ||
var ret = this.saddr + " -> " + this.daddr; | ||
var ret = this.saddr + " -> " + this.daddr + " "; | ||
var flags = this.flags.toString(); | ||
if (flags.length > 2) { | ||
ret += " flags " + flags; | ||
ret += "flags " + flags + " "; | ||
} | ||
switch (this.protocol) { | ||
case 1: | ||
ret += " ICMP"; | ||
break; | ||
case 2: | ||
ret += " IGMP"; | ||
break; | ||
case 4: | ||
ret += " IPv4_in_IPv4"; // IPv4 encapsulation, RFC2003 | ||
break; | ||
case 6: | ||
ret += " TCP"; | ||
break; | ||
case 17: | ||
ret += " UDP"; | ||
break; | ||
case 41: | ||
ret += " IPv6_in_IP4"; // IPv6 encapsulation, RFC2473 | ||
break; | ||
default: | ||
ret += " proto " + this.protocol; | ||
if(this.payload === undefined || this.payload === null ){ | ||
ret += "proto " + this.protocol; | ||
} else { | ||
ret += this.payload.constructor.name; | ||
} | ||
@@ -142,0 +125,0 @@ return ret + " " + this.payload; |
@@ -1,23 +0,24 @@ | ||
var map = require("../util").int8_to_hex_nopad; | ||
var hex = require("../util").int8_to_hex; | ||
function IPv6Addr() { | ||
this.o1 = null; | ||
this.o2 = null; | ||
this.o3 = null; | ||
this.o4 = null; | ||
this.o5 = null; | ||
this.o6 = null; | ||
this.o7 = null; | ||
this.o8 = null; | ||
this.addr = new Array(16); | ||
} | ||
IPv6Addr.prototype.decode = function (raw_packet, offset) { | ||
this.o1 = raw_packet.readUInt16LE[offset]; | ||
this.o2 = raw_packet.readUInt16LE[offset + 2]; | ||
this.o3 = raw_packet.readUInt16LE[offset + 4]; | ||
this.o4 = raw_packet.readUInt16LE[offset + 6]; | ||
this.o5 = raw_packet.readUInt16LE[offset + 8]; | ||
this.o6 = raw_packet.readUInt16LE[offset + 10]; | ||
this.o7 = raw_packet.readUInt16LE[offset + 12]; | ||
this.o8 = raw_packet.readUInt16LE[offset + 14]; | ||
IPv6Addr.prototype.decode = function decode(raw_packet, offset) { | ||
this.addr[0] = raw_packet[offset + 0]; | ||
this.addr[1] = raw_packet[offset + 1]; | ||
this.addr[2] = raw_packet[offset + 2]; | ||
this.addr[3] = raw_packet[offset + 3]; | ||
this.addr[4] = raw_packet[offset + 4]; | ||
this.addr[5] = raw_packet[offset + 5]; | ||
this.addr[6] = raw_packet[offset + 6]; | ||
this.addr[7] = raw_packet[offset + 7]; | ||
this.addr[8] = raw_packet[offset + 8]; | ||
this.addr[9] = raw_packet[offset + 9]; | ||
this.addr[10] = raw_packet[offset + 10]; | ||
this.addr[11] = raw_packet[offset + 11]; | ||
this.addr[12] = raw_packet[offset + 12]; | ||
this.addr[13] = raw_packet[offset + 13]; | ||
this.addr[14] = raw_packet[offset + 14]; | ||
this.addr[15] = raw_packet[offset + 15]; | ||
@@ -27,17 +28,17 @@ return this; | ||
function format(num) { | ||
var p1 = (num & 0xff00) >> 8; | ||
var p2 = num & 0x00ff; | ||
if (p1 === 0) { | ||
return map[p2]; | ||
} else { | ||
return map[p1] + map[p2]; | ||
} | ||
} | ||
IPv6Addr.prototype.decoderName = "ipv6-addr"; | ||
IPv6Addr.prototype.eventsOnDecode = false; | ||
IPv6Addr.prototype.toString = function () { | ||
return format(this.o1) + ":" + format(this.o2) + ":" + format(this.o3) + ":" + format(this.o4) + ":" + | ||
format(this.o5) + ":" + format(this.o6) + ":" + format(this.o7) + ":" + format(this.o8); | ||
//There are some rules one can follow to | ||
//shorten the string representation of an | ||
//ipv6 address, but the long hand version | ||
//is both simple and valid. | ||
return hex[this.addr[0]] + hex[this.addr[1]] + ":" + hex[this.addr[2]] + hex[this.addr[3]] + ":" + | ||
hex[this.addr[4]] + hex[this.addr[5]] + ":" + hex[this.addr[6]] + hex[this.addr[7]] + ":" + | ||
hex[this.addr[8]] + hex[this.addr[9]] + ":" + hex[this.addr[10]] + hex[this.addr[11]] + ":" + | ||
hex[this.addr[12]] + hex[this.addr[13]] + ":" + hex[this.addr[14]] + hex[this.addr[15]]; | ||
}; | ||
module.exports = IPv6Addr; |
@@ -1,99 +0,60 @@ | ||
var ICMP = require("./icmp"); | ||
var IGMP = require("./igmp"); | ||
var TCP = require("./tcp"); | ||
var UDP = require("./udp"); | ||
var IPv4 = require("./ipv4"); | ||
var IPv6Addr = require("./ipv6_addr"); | ||
var protocols = require("./ip_protocols"); | ||
function IPv6Header() { | ||
function IPv6(emitter) { | ||
this.emitter = emitter; | ||
this.version = undefined; | ||
this.trafficClass = undefined; | ||
this.flowLabel = undefined; | ||
this.payloadLength = undefined; | ||
this.nextHeader = undefined; | ||
this.hopLimit = undefined; | ||
this.saddr = undefined; | ||
this.daddr = undefined; | ||
this.payload = undefined; | ||
} | ||
IPv6Header.prototype.decode = function (raw_packet, next_header, ip, offset) { | ||
switch (next_header) { | ||
case 1: | ||
ip.payload = new ICMP().decode(raw_packet, offset); | ||
break; | ||
case 2: | ||
ip.payload = new IGMP().decode(raw_packet, offset); | ||
break; | ||
case 4: | ||
ip.payload = new IPv4().decode(raw_packet, offset); // IPv4 encapsulation, RFC2003 | ||
break; | ||
case 6: | ||
ip.payload = new TCP().decode(raw_packet, offset, ip); | ||
break; | ||
case 17: | ||
ip.payload = new UDP().decode(raw_packet, offset); | ||
break; | ||
case 41: | ||
ip.payload = new IPv6().decode(raw_packet, offset); // IPv6 encapsulation, RFC2473 | ||
break; | ||
/* Please follow numbers and RFC in http://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml#extension-header | ||
* Not all next protocols follow this rule (and we can have unsuported upper protocols here too). | ||
* */ | ||
case 0: //Hop-by-Hop | ||
case 60: //Destination Options | ||
case 43: //Routing | ||
case 135: //Mobility | ||
case 139: //Host Identity Protocol. //Discussion: rfc5201 support only No Next Header/trailing data, but future documents May do. | ||
case 140: //Shim6 Protocol | ||
new IPv6Header().decode(raw_packet, raw_packet[offset], ip, offset + 8*raw_packet[offset+1] + 8); | ||
break; | ||
case 51: //Authentication Header | ||
new IPv6Header().decode(raw_packet, raw_packet[offset], ip, offset + 4*raw_packet[offset+1] + 8); | ||
break; | ||
default: | ||
// 59 - No next Header, and unknowed upper layer protocols, do nothing. | ||
} | ||
}; | ||
function IPv6() { | ||
} | ||
IPv6.prototype.decode = function (raw_packet, offset) { | ||
// http://en.wikipedia.org/wiki/IPv6 | ||
this.version = (raw_packet[offset] & 240) >> 4; // first 4 bits | ||
this.traffic_class = ((raw_packet[offset] & 15) << 4) + ((raw_packet[offset+1] & 240) >> 4); | ||
this.flow_label = ((raw_packet[offset + 1] & 15) << 16) + | ||
var originalOffset = offset; | ||
this.version = ((raw_packet[offset] & 0xf0) >> 4); // first 4 bits | ||
this.trafficClass = ((raw_packet[offset] & 0x0f) << 4) | ((raw_packet[offset+1] & 0xf0) >> 4); | ||
this.flowLabel = ((raw_packet[offset + 1] & 0x0f) << 16) + | ||
(raw_packet[offset + 2] << 8) + | ||
raw_packet[offset + 3]; | ||
this.payload_length = raw_packet.readUInt16BE(offset+4, true); | ||
this.total_length = this.payload_length + 40; | ||
this.next_header = raw_packet[offset+6]; | ||
this.hop_limit = raw_packet[offset+7]; | ||
this.payloadLength = raw_packet.readUInt16BE(offset+4, true); | ||
this.nextHeader = raw_packet[offset+6]; | ||
this.hopLimit = raw_packet[offset+7]; | ||
this.saddr = new IPv6Addr().decode(raw_packet, offset+8); | ||
this.daddr = new IPv6Addr().decode(raw_packet, offset+24); | ||
this.header_bytes = 40; | ||
new IPv6Header().decode(raw_packet, this.next_header, this, offset+40); | ||
/* | ||
http://tools.ietf.org/html/rfc2780 | ||
* 5.3 IPv6 Next Header field | ||
* | ||
* The IPv6 Next Header field carries values from the same name space as | ||
* the IPv4 Protocol name space. | ||
*/ | ||
offset = originalOffset + 40; | ||
var ProtocolDecoder = protocols[this.nextHeader]; | ||
if(ProtocolDecoder === undefined) { | ||
this.protocolName = "Unknown"; | ||
} else { | ||
this.payload = new ProtocolDecoder().decode(raw_packet, offset, raw_packet.length - 40); | ||
} | ||
if(this.emitter) { this.emitter.emit("ipv6", this); } | ||
return this; | ||
}; | ||
IPv6.prototype.decoderName = "ipv6"; | ||
IPv6.prototype.eventsOnDecode = true; | ||
IPv6.prototype.toString = function () { | ||
var ret = this.saddr + " -> " + this.daddr; | ||
var ret = this.saddr + " -> " + this.daddr + " "; | ||
switch (this.next_header) { | ||
case 1: | ||
ret += " ICMP"; | ||
break; | ||
case 2: | ||
ret += " IGMP"; | ||
break; | ||
case 4: | ||
ret += " IPv4_in_IPv6"; // IPv4 encapsulation, RFC2003 | ||
break; | ||
case 6: | ||
ret += " TCP"; | ||
break; | ||
case 17: | ||
ret += " UDP"; | ||
break; | ||
case 41: | ||
ret += " IPv6_in_IPv6"; // IPv6 encapsulation, RFC2473 | ||
break; | ||
default: | ||
ret += " proto " + this.next_header; | ||
if(this.payload === undefined || this.payload === null ){ | ||
ret += "proto " + this.nextHeader; | ||
} else { | ||
ret += this.payload.constructor.name; | ||
} | ||
@@ -100,0 +61,0 @@ |
var IPv4 = require("./ipv4"); | ||
var IPv6 = require("./ipv6"); | ||
var ARP = require("./arp"); | ||
function LogicalLinkControl() { | ||
this.dsap = null; | ||
this.ssap = null; | ||
this.control_field = null; | ||
this.org_code = null; | ||
this.type = null; | ||
function LogicalLinkControl(emitter) { | ||
this.emitter = emitter; | ||
this.dsap = undefined; | ||
this.ssap = undefined; | ||
this.controlField = undefined; | ||
this.orgCode = undefined; | ||
this.type = undefined; | ||
this._error = undefined; | ||
} | ||
@@ -15,5 +19,10 @@ | ||
if (((this.dsap === 0xaa) && (this.ssap === 0xaa)) || ((this.dsap === 0x00) && (this.ssap === 0x00))) { | ||
this.control_field = raw_packet[offset++]; | ||
this.org_code = [ | ||
// https://en.wikipedia.org/wiki/IEEE_802.2#LSAP_Values | ||
// http://tools.ietf.org/html/rfc1700 | ||
// 0xaa is SNAP | ||
// 0x00 is NULL LSAP | ||
if (((this.dsap === 0xaa) && (this.ssap === 0xaa)) || | ||
((this.dsap === 0x00) && (this.ssap === 0x00))) { | ||
this.controlField = raw_packet[offset++]; | ||
this.orgCode = [ | ||
raw_packet[offset++], | ||
@@ -23,15 +32,31 @@ raw_packet[offset++], | ||
]; | ||
this.type = raw_packet.readUInt16BE(raw_packet, offset); | ||
offset += 2; | ||
this.type = raw_packet.readUInt16BE(offset); offset += 2; | ||
switch (this.type) { | ||
case 0x0800: // IPv4 | ||
this.payload = new IPv4().decode(raw_packet, offset); | ||
break; | ||
if (this.ethertype < 1536) { | ||
// this packet is actually some 802.3 type without an ethertype | ||
this.ethertype = 0; | ||
} else { | ||
switch (this.type) { | ||
case 0x0800: // IPv4 | ||
this.payload = new IPv4(this.emitter).decode(raw_packet, offset); | ||
break; | ||
case 0x0806: // ARP | ||
this.payload = new ARP(this.emitter).decode(raw_packet, offset); | ||
break; | ||
case 0x86dd: // IPv6 | ||
this.payload = new IPv6(this.emitter).decode(raw_packet, offset); | ||
break; | ||
} | ||
} | ||
} else { | ||
throw new Error("Unknown LLC types: DSAP: " + this.dsap + ", SSAP: " + this.ssap); | ||
this._error = "Unknown LLC types: DSAP: " + this.dsap + ", SSAP: " + this.ssap; | ||
} | ||
if(this.emitter) { this.emitter.emit("llc", this); } | ||
return this; | ||
}; | ||
LogicalLinkControl.prototype.decoderName = "llc"; | ||
LogicalLinkControl.prototype.eventsOnDecode = true; | ||
module.exports = LogicalLinkControl; |
var IPv4 = require("./ipv4"); | ||
var IPv6 = require("./ipv6"); | ||
function NullPacket() { | ||
this.pftype = null; | ||
this.payload = null; | ||
function NullPacket(emitter) { | ||
this.emitter = emitter; | ||
this.pftype = undefined; | ||
this.payload = undefined; | ||
this._error = undefined; | ||
} | ||
@@ -20,7 +22,7 @@ | ||
if (this.pftype === 2) { // AF_INET, at least on my Linux and OSX machines right now | ||
this.payload = new IPv4().decode(raw_packet, offset + 4); | ||
this.payload = new IPv4(this.emitter).decode(raw_packet, offset + 4); | ||
} else if (this.pftype === 30) { // AF_INET6, often | ||
this.payload = new IPv6().decode(raw_packet, offset + 4); | ||
this.payload = new IPv6(this.emitter).decode(raw_packet, offset + 4); | ||
} else { | ||
console.log("pcap.js: decode.nulltype() - Don't know how to decode protocol family " + this.pftype); | ||
this._error = "unknown protocol family " + this.pftype; | ||
} | ||
@@ -31,2 +33,5 @@ | ||
NullPacket.prototype.decoderName = "null-packet"; | ||
NullPacket.prototype.eventsOnDecode = false; | ||
NullPacket.prototype.toString = function () { | ||
@@ -33,0 +38,0 @@ return this.pftype + " " + this.payload; |
var EthernetPacket = require("./ethernet_packet"); | ||
var NullPacket = require("./null_packet"); | ||
var RawPacket = require("./raw_packet"); | ||
var RadioPacket = require("./radio_packet"); | ||
var Ipv4 = require("./ipv4"); | ||
var RadioPacket = require("./ieee802.11/radio_packet"); | ||
var SLLPacket = require("./sll_packet"); | ||
@@ -22,6 +22,7 @@ | ||
function PcapPacket() { | ||
function PcapPacket(emitter) { | ||
this.link_type = null; | ||
this.pcap_header = null; | ||
this.payload = null; | ||
this.emitter = emitter; | ||
} | ||
@@ -33,19 +34,19 @@ | ||
var buf = packet_with_header.buf; | ||
var buf = packet_with_header.buf.slice(0, this.pcap_header.len); | ||
switch (this.link_type) { | ||
case "LINKTYPE_ETHERNET": | ||
this.payload = new EthernetPacket().decode(buf, 0); | ||
this.payload = new EthernetPacket(this.emitter).decode(buf, 0); | ||
break; | ||
case "LINKTYPE_NULL": | ||
this.payload = new NullPacket().decode(buf, 0); | ||
this.payload = new NullPacket(this.emitter).decode(buf, 0); | ||
break; | ||
case "LINKTYPE_RAW": | ||
this.payload = new RawPacket().decode(buf, 0); | ||
this.payload = new Ipv4(this.emitter).decode(buf, 0); | ||
break; | ||
case "LINKTYPE_IEEE802_11_RADIO": | ||
this.payload = new RadioPacket.decode(buf, 0); | ||
this.payload = new RadioPacket(this.emitter).decode(buf, 0); | ||
break; | ||
case "LINKTYPE_LINUX_SLL": | ||
this.payload = new SLLPacket().decode(buf, 0); | ||
this.payload = new SLLPacket(this.emitter).decode(buf, 0); | ||
break; | ||
@@ -52,0 +53,0 @@ default: |
@@ -10,2 +10,5 @@ var util = require("../util"); | ||
SLLAddr.prototype.decoderName = "ssl-addr"; | ||
SLLAddr.prototype.eventsOnDecode = false; | ||
SLLAddr.prototype.toString = function () { | ||
@@ -12,0 +15,0 @@ var ret = ""; |
@@ -9,3 +9,4 @@ // Synthetic Link Layer used by Linux to support the "any" pseudo device | ||
function SLLPacket () { | ||
function SLLPacket (emitter) { | ||
this.emitter = emitter; | ||
this.packet_type = null; | ||
@@ -38,9 +39,9 @@ this.address_type = null; | ||
case 0x800: // IPv4 | ||
this.payload = new IPv4().decode(raw_packet, offset); | ||
this.payload = new IPv4(this.emitter).decode(raw_packet, offset); | ||
break; | ||
case 0x806: // ARP | ||
this.payload = new Arp().decode(raw_packet, offset); | ||
this.payload = new Arp(this.emitter).decode(raw_packet, offset); | ||
break; | ||
case 0x86dd: // IPv6 - http://en.wikipedia.org/wiki/IPv6 | ||
this.payload = new IPv6().decode(raw_packet, offset); | ||
this.payload = new IPv6(this.emitter).decode(raw_packet, offset); | ||
break; | ||
@@ -58,2 +59,5 @@ case 0x88cc: // LLDP - http://en.wikipedia.org/wiki/Link_Layer_Discovery_Protocol | ||
SLLPacket.prototype.decoderName = "ssl-packet"; | ||
SLLPacket.prototype.eventsOnDecode = false; | ||
SLLPacket.prototype.toString = function () { | ||
@@ -60,0 +64,0 @@ var ret = ""; |
function TCPFlags() { | ||
this.cwr = null; | ||
this.ece = null; | ||
this.urg = null; | ||
this.ack = null; | ||
this.psh = null; | ||
this.rst = null; | ||
this.syn = null; | ||
this.fin = null; | ||
function TCPFlags(emitter) { | ||
this.emitter = emitter; | ||
this.nonce = undefined; | ||
this.cwr = undefined; | ||
this.ece = undefined; | ||
this.urg = undefined; | ||
this.ack = undefined; | ||
this.psh = undefined; | ||
this.rst = undefined; | ||
this.syn = undefined; | ||
this.fin = undefined; | ||
} | ||
TCPFlags.prototype.decode = function (first_byte, second_byte) { | ||
this.nonce = Boolean(first_byte & 16); | ||
this.cwr = Boolean(second_byte & 128); | ||
this.ece = Boolean(second_byte & 64); | ||
this.urg = Boolean(second_byte & 32); | ||
this.ack = Boolean(second_byte & 16); | ||
this.psh = Boolean(second_byte & 8); | ||
this.rst = Boolean(second_byte & 4); | ||
this.syn = Boolean(second_byte & 2); | ||
this.fin = Boolean(second_byte & 1); | ||
return this; | ||
}; | ||
TCPFlags.prototype.toString = function () { | ||
@@ -127,2 +142,9 @@ var ret = "["; | ||
break; | ||
case 254: | ||
case 255: | ||
//We do not know how to parse rfc6994 (Experimental TCP option) | ||
//however, the first byte is the length of the option (including | ||
//the 1 byte kind, and 1 byte of length.) So skip over option. | ||
offset += raw_packet.readUInt8(offset + 1); | ||
break; | ||
default: | ||
@@ -158,17 +180,17 @@ throw new Error("Don't know how to process TCP option " + raw_packet[offset]); | ||
function TCP() { | ||
this.sport = null; | ||
this.dport = null; | ||
this.seqno = null; | ||
this.ackno = null; | ||
this.data_offset = null; | ||
this.header_bytes = null; // not part of packet but handy | ||
this.reserved = null; | ||
this.flags = new TCPFlags(); | ||
this.window_size = null; | ||
this.checksum = null; | ||
this.urgent_pointer = null; | ||
this.options = null; | ||
this.data = null; | ||
this.data_bytes = null; | ||
function TCP(emitter) { | ||
this.emitter = emitter; | ||
this.sport = undefined; | ||
this.dport = undefined; | ||
this.seqno = undefined; | ||
this.ackno = undefined; | ||
this.headerLength = undefined; | ||
this.reserved = undefined; | ||
this.flags = undefined; | ||
this.windowSize = undefined; | ||
this.checksum = undefined; | ||
this.urgentPointer = undefined; | ||
this.options = undefined; | ||
this.data = undefined; | ||
this.dataLength = undefined; | ||
} | ||
@@ -180,2 +202,4 @@ | ||
// } | ||
TCP.prototype.decoderName = "tcp"; | ||
TCP.prototype.eventsOnDecode = true; | ||
@@ -194,28 +218,17 @@ // http://en.wikipedia.org/wiki/Transmission_Control_Protocol | ||
offset += 4; | ||
this.data_offset = (raw_packet[offset] & 0xf0) >> 4; // first 4 bits of 12 | ||
if (this.data_offset < 5 || this.data_offset > 15) { | ||
throw new Error("invalid data_offset: " + this.data_offset); | ||
} | ||
this.header_bytes = this.data_offset * 4; // convenience for using data_offset | ||
this.reserved = raw_packet[offset] & 15; // second 4 bits of 12 | ||
offset += 1; | ||
var all_flags = raw_packet[offset]; | ||
this.flags.cwr = (all_flags & 128) >> 7; // all flags packed into 13 | ||
this.flags.ece = (all_flags & 64) >> 6; | ||
this.flags.urg = (all_flags & 32) >> 5; | ||
this.flags.ack = (all_flags & 16) >> 4; | ||
this.flags.psh = (all_flags & 8) >> 3; | ||
this.flags.rst = (all_flags & 4) >> 2; | ||
this.flags.syn = (all_flags & 2) >> 1; | ||
this.flags.fin = all_flags & 1; | ||
offset += 1; | ||
this.window_size = raw_packet.readUInt16BE(offset, true); // 14, 15 | ||
// The first 4 bits of the next header * 4 tells use the length | ||
// of the header. | ||
this.headerLength = (raw_packet[offset] & 0xf0) >> 2; | ||
this.flags = new TCPFlags().decode(raw_packet[offset], raw_packet[offset+1]); | ||
offset += 2; | ||
this.windowSize = raw_packet.readUInt16BE(offset, true); // 14, 15 | ||
offset += 2; | ||
this.checksum = raw_packet.readUInt16BE(offset, true); // 16, 17 | ||
offset += 2; | ||
this.urgent_pointer = raw_packet.readUInt16BE(offset, true); // 18, 19 | ||
this.urgentPointer = raw_packet.readUInt16BE(offset, true); // 18, 19 | ||
offset += 2; | ||
this.options = new TCPOptions(); | ||
var options_len = this.header_bytes - (offset - orig_offset); | ||
var options_len = this.headerLength - (offset - orig_offset); | ||
if (options_len > 0) { | ||
@@ -226,10 +239,16 @@ this.options.decode(raw_packet, offset, options_len); | ||
this.data_bytes = len - this.header_bytes; | ||
if (this.data_bytes > 0) { | ||
this.dataLength = len - this.headerLength; | ||
if (this.dataLength > 0) { | ||
// add a buffer slice pointing to the data area of this TCP packet. | ||
// Note that this does not make a copy, so ret.data is only valid for this current | ||
// trip through the capture loop. | ||
this.data = raw_packet.slice(offset, offset + this.data_bytes); | ||
this.data = raw_packet.slice(offset, offset + this.dataLength); | ||
} else { | ||
// null indicated the value was set. Where as undefined | ||
// means the value was never set. Since there is no data | ||
// we explicity want to communicate this to consumers. | ||
this.data = null; | ||
} | ||
if(this.emitter) { this.emitter.emit("tcp", this); } | ||
return this; | ||
@@ -240,8 +259,8 @@ }; | ||
var ret = this.sport + "->" + this.dport + " seq " + this.seqno + " ack " + this.ackno + " flags " + this.flags + " " + | ||
"win " + this.window_size + " csum " + this.checksum; | ||
"win " + this.windowSize + " csum " + this.checksum; | ||
if (this.urgent_pointer) { | ||
ret += " urg " + this.urgent_pointer; | ||
ret += " urg " + this.urgentPointer; | ||
} | ||
ret += " " + this.options.toString(); | ||
ret += " len " + this.data_bytes; | ||
ret += " len " + this.dataLength; | ||
return ret; | ||
@@ -248,0 +267,0 @@ }; |
var DNS = require("./dns"); | ||
function UDP() { | ||
this.sport = null; | ||
this.dport = null; | ||
this.length = null; | ||
this.checksum = null; | ||
this.data = null; | ||
function UDP(emitter) { | ||
this.emitter = emitter; | ||
this.sport = undefined; | ||
this.dport = undefined; | ||
this.length = undefined; | ||
this.checksum = undefined; | ||
this.data = undefined; | ||
} | ||
@@ -24,5 +25,9 @@ | ||
if(this.emitter) { this.emitter.emit("udp", this); } | ||
return this; | ||
}; | ||
UDP.prototype.decoderName = "udp"; | ||
UDP.prototype.eventsOnDecode = true; | ||
UDP.prototype.toString = function () { | ||
@@ -29,0 +34,0 @@ var ret = "UDP " + this.sport + "->" + this.dport + " len " + this.length; |
@@ -16,2 +16,5 @@ function Vlan() { | ||
Vlan.prototype.decoderName = "vlan"; | ||
Vlan.prototype.eventsOnDecode = false; | ||
Vlan.prototype.toString = function () { | ||
@@ -18,0 +21,0 @@ return this.priority + " " + this.canonical_format + " " + this.id; |
@@ -0,1 +1,2 @@ | ||
var events = require("events"); | ||
// Meaningfully hold the different types of frames at some point | ||
@@ -2,0 +3,0 @@ function WebSocketFrame() { |
@@ -1,2 +0,2 @@ | ||
var pcap = require("pcap"), | ||
var pcap = require("../pcap"), | ||
pcap_session = pcap.createSession("", "tcp"), | ||
@@ -3,0 +3,0 @@ matcher = /safari/i; |
{ | ||
"name": "pcap", | ||
"version": "2.0.1", | ||
"version": "2.1.0", | ||
"description": "raw packet capture, decoding, and analysis", | ||
"author": "Matt Ranney <mjr@ranney.com>", | ||
"maintainers": [ | ||
"Ujjwal Thaakar <ujjwalthaakar@gmail.com>" | ||
], | ||
"main": "./pcap", | ||
@@ -11,6 +14,25 @@ "repository": { | ||
}, | ||
"engines": { | ||
"node": ">=0.10" | ||
}, | ||
"dependencies": { | ||
"nan": "~1.6.1", | ||
"socketwatcher": "git://github.com/zerouid/node-socketwatcher.git" | ||
"nan": "^2.0.9", | ||
"socketwatcher": "git+https://github.com/bytzdev/node-socketwatcher.git" | ||
}, | ||
"devDependencies": { | ||
"grunt": "^0.4.5", | ||
"grunt-cli": "^0.1.13", | ||
"grunt-contrib-jshint": "^0.11.0", | ||
"grunt-coveralls": "^1.0.0", | ||
"grunt-mocha-istanbul": "^2.3.1", | ||
"grunt-mocha-test": "^0.12.7", | ||
"istanbul": "^0.3.5", | ||
"mocha": "^2.1.0", | ||
"mocha-sinon": "^1.1.4", | ||
"should": "^5.0.0", | ||
"sinon": "^1.14.1" | ||
}, | ||
"scripts": { | ||
"test": "grunt" | ||
} | ||
} |
10
pcap.js
@@ -8,2 +8,3 @@ var util = require("util"); | ||
var DNSCache = require("./dns_cache"); | ||
var timers = require("timers"); | ||
@@ -72,3 +73,3 @@ exports.decode = decode; | ||
} else { | ||
setImmediate(function() { | ||
timers.setImmediate(function() { | ||
var packets = 0; | ||
@@ -88,3 +89,3 @@ do { | ||
PcapSession.prototype.findalldevs = function () { | ||
exports.findalldevs = function () { | ||
return binding.findalldevs(); | ||
@@ -107,3 +108,5 @@ }; | ||
this.session.close(); | ||
this.readWatcher.stop(); | ||
if (this.is_live) { | ||
this.readWatcher.stop(); | ||
} | ||
// TODO - remove listeners so program will exit I guess? | ||
@@ -130,2 +133,1 @@ }; | ||
}; | ||
364
README.md
@@ -0,4 +1,10 @@ | ||
##Disclaimer | ||
node_pcap is currently being heavily refactored much of the documentation is out of date. If you installed node_pcap from npm go to [v2.0.1](https://github.com/mranney/node_pcap/commit/6e4d56671c54e0cf690f72b92554a538244bd1b6). Thanks for your patience and contributions as we work on the next major version of node_pcap. | ||
node_pcap | ||
========= | ||
[![Join the chat at https://gitter.im/mranney/node_pcap](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mranney/node_pcap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
[![Build Status](https://travis-ci.org/mranney/node_pcap.svg?branch=master)](https://travis-ci.org/mranney/node_pcap)[![Coverage Status](https://coveralls.io/repos/mranney/node_pcap/badge.svg)](https://coveralls.io/r/mranney/node_pcap) | ||
This is a set of bindings from `libpcap` to node as well as some useful libraries to decode, print, and | ||
@@ -10,3 +16,3 @@ analyze packets. `libpcap` is a packet capture library used by programs like `tcpdump` and `wireshark`. | ||
to use this package are | ||
[http_trace](https://github.com/mranney/http_trace), and | ||
[http_trace](https://github.com/mranney/http_trace) (works only on node 4), and | ||
[htracr](https://github.com/mnot/htracr). | ||
@@ -59,3 +65,3 @@ | ||
To use this library in your own program, `pcap.js` and `pcap_binding.node` must be in `NODE_PATH`. `npm` | ||
To use this library in your own program, `pcap.js` and `pcap_binding.node` must be in `NODE_PATH`. `npm` | ||
takes care of this automatically. | ||
@@ -67,4 +73,6 @@ | ||
var pcap = require('pcap'), | ||
pcap_session = pcap.createSession(interface, filter); | ||
```javascript | ||
var pcap = require('pcap'), | ||
pcap_session = pcap.createSession(interface, filter); | ||
``` | ||
@@ -87,8 +95,10 @@ `interface` is the name of the interface on which to capture packets. If passed an empty string, `libpcap` | ||
pcap_session.on('packet', function (raw_packet) { | ||
// do some stuff with a raw packet | ||
}); | ||
```javascript | ||
pcap_session.on('packet', function (raw_packet) { | ||
// do some stuff with a raw packet | ||
}); | ||
``` | ||
To convert `raw_packet` into a JavaScript object that is easy to work with, decode it: | ||
var packet = pcap.decode.packet(raw_packet); | ||
@@ -99,3 +109,5 @@ | ||
packet.link.ip.tcp.dport | ||
```javascript | ||
packet.link.ip.tcp.dport | ||
``` | ||
@@ -106,84 +118,27 @@ This structure is easy to explore with `sys.inspect`. | ||
TCP can be analyzed by feeding the packets into a `TCP_tracker` and then listening for `start` and `end` events. | ||
TCP can be analyzed by feeding the packets into a `TCPTracker` and then listening for `session` and `end` events. | ||
var pcap = require('pcap'), | ||
tcp_tracker = new pcap.TCP_tracker(), | ||
pcap_session = pcap.createSession(interface, "ip proto \\tcp"); | ||
```javascript | ||
var pcap = require('pcap'), | ||
tcp_tracker = new pcap.TCPTracker(), | ||
pcap_session = pcap.createSession('en0', "ip proto \\tcp"); | ||
tcp_tracker.on('start', function (session) { | ||
console.log("Start of TCP session between " + session.src_name + " and " + session.dst_name); | ||
}); | ||
tcp_tracker.on('session', function (session) { | ||
console.log("Start of session between " + session.src_name + " and " + session.dst_name); | ||
session.on('end', function (session) { | ||
console.log("End of TCP session between " + session.src_name + " and " + session.dst_name); | ||
}); | ||
}); | ||
tcp_tracker.on('end', function (session) { | ||
console.log("End of TCP session between " + session.src_name + " and " + session.dst_name); | ||
}); | ||
pcap_session.on('packet', function (raw_packet) { | ||
var packet = pcap.decode.packet(raw_packet); | ||
tcp_tracker.track_packet(packet); | ||
}); | ||
``` | ||
pcap_session.on('packet', function (raw_packet) { | ||
var packet = pcap.decode.packet(raw_packet); | ||
tcp_tracker.track_packet(packet); | ||
}); | ||
You must only send IPv4 TCP packets to the TCP tracker. Explore the `session` object with `sys.inspect` to | ||
see the wonderful things it can do for you. Hopefully the names of the properties are self-explanatory: | ||
{ src: '10.51.2.130:55965' | ||
, dst: '75.119.207.0:80' | ||
, syn_time: 1280425738896.771 | ||
, state: 'ESTAB' | ||
, key: '10.51.2.130:55965-75.119.207.0:80' | ||
, send_isn: 2869922608 | ||
, send_window_scale: 8 | ||
, send_packets: { '2869922609': 1280425738896.771 } | ||
, send_acks: { '1063203923': 1280425738911.618 } | ||
, send_retrans: {} | ||
, send_next_seq: 2869922609 | ||
, send_acked_seq: null | ||
, send_bytes_ip: 60 | ||
, send_bytes_tcp: 108 | ||
, send_bytes_payload: 144 | ||
, recv_isn: 1063203922 | ||
, recv_window_scale: 128 | ||
, recv_packets: { '1063203923': 1280425738911.536 } | ||
, recv_acks: { '2869922609': 1280425738911.536 } | ||
, recv_retrans: {} | ||
, recv_next_seq: null | ||
, recv_acked_seq: null | ||
, recv_bytes_ip: 20 | ||
, recv_bytes_tcp: 40 | ||
, recv_bytes_payload: 0 | ||
, src_name: '10.51.2.130:55965' | ||
, dst_name: '75.119.207.0:80' | ||
, current_cap_time: 1280425738911.65 | ||
See [http_trace](https://github.com/mranney/http_trace) for an example of how to use these events to decode HTTP (Works only on node 4). | ||
### HTTP Analysis | ||
The `TCP_tracker` also detects and decodes HTTP on all streams it receives. If HTTP is detected, several | ||
new events will be emitted: | ||
* `http request`: function(session, http) | ||
* `http request body`: function(session, http, data) | ||
Note that `data` is a node Buffer object sliced from the original packet. If you want to use it past the | ||
current tick, you'll need to make a copy somehow. | ||
* `http request complete`: function(session, http) | ||
* `http response`: function(session, http) | ||
* `http response body`: function(session, http, data) | ||
`data` is a Buffer slice. See above. | ||
* `http response complete`: function(session, http) | ||
See `http_trace` for an example of how to use these events to decode HTTP. | ||
### WebSocket Analysis | ||
The `TCP_tracker` further detects and decodes WebSocket traffic on all streams it receives. | ||
* `websocket upgrade`: function(session, http) | ||
* `websocket message`: function(session, dir, message) | ||
See `http_trace` for an example of how to use these events to decode WebSocket. | ||
## Some Common Problems | ||
@@ -193,3 +148,3 @@ | ||
TSO is a technique that modern operating systems use to offload the burden of IP/TCP header computation to | ||
TSO is a technique that modern operating systems use to offload the burden of IP/TCP header computation to | ||
the network hardware. It also reduces the number of times that data is moved data between the kernel and the | ||
@@ -199,3 +154,3 @@ network hardware. TSO saves CPU when sending data that is larger than a single IP packet. | ||
This is amazing and wonderful, but it does make some kinds of packet sniffing more difficult. In many cases, | ||
it is important to see the exact packets that are sent, but if the network hardware is sending the packets, | ||
it is important to see the exact packets that are sent, but if the network hardware is sending the packets, | ||
these are not available to `libpcap`. The solution is to disable TSO. | ||
@@ -206,3 +161,3 @@ | ||
sudo sysctl -w net.inet.tcp.tso=0 | ||
Linux (substitute correct interface name): | ||
@@ -222,3 +177,3 @@ | ||
sudo http_trace lo0 "ip proto \tcp" | ||
The backslash is important. The pcap filter language has an ambiguity with the word "tcp", so by escaping it, | ||
@@ -238,237 +193,8 @@ you'll get the correct interpretation for this case. | ||
## examples/simple_capture | ||
## Examples | ||
This program captures packets and prints them using the built in simple printer. Here's a sample of it's output. | ||
In another window I ran `curl nodejs.org`. | ||
[redis_trace](https://github.com/mranney/redis_trace) | ||
mjr:~/work/node_pcap$ sudo node examples/simple_capture.js en1 "" | ||
libpcap version 1.0.0 | ||
en0 no address | ||
* en1 10.240.0.133/255.255.255.0 | ||
lo0 127.0.0.1/255.0.0.0 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 10.240.0.1 ARP request 10.240.0.133 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c 10.240.0.133 ARP reply 10.240.0.1 hwaddr 00:18:39:ff:f9:1c | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c 10.240.0.133:53808 -> 97.107.132.72:80 TCP len 64 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c 10.240.0.133:57052 -> 10.240.0.1:53 DNS question 133.0.240.10.in-addr.arpa PTR | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c 10.240.0.133:57052 -> 10.240.0.1:53 DNS question 72.132.107.97.in-addr.arpa PTR | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c 10.240.0.133:57052 -> 10.240.0.1:53 DNS question 1.0.240.10.in-addr.arpa PTR | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 10.240.0.1:53 -> 10.240.0.133:57052 DNS answer 133.0.240.10.in-addr.arpa PTR | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 10.240.0.1:53 -> rv-mjr2.ranney.com:57052 DNS answer 72.132.107.97.in-addr.arpa PTR | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 10.240.0.1:53 -> rv-mjr2.ranney.com:57052 DNS answer 1.0.240.10.in-addr.arpa PTR | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 60 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 196 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 52 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 1500 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 337 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
00:18:39:ff:f9:1c -> 00:1f:5b:ce:3e:29 tinyclouds.org:80 -> rv-mjr2.ranney.com:53808 TCP len 52 | ||
00:1f:5b:ce:3e:29 -> 00:18:39:ff:f9:1c rv-mjr2.ranney.com:53808 -> tinyclouds.org:80 TCP len 52 | ||
[http_trace](https://github.com/mranney/http_trace) (Node 4 only) | ||
## Output from `session.findalldevs`: | ||
[ { name: 'en0' | ||
, addresses: | ||
[ { addr: '10.51.2.183' | ||
, netmask: '255.255.255.0' | ||
, broadaddr: '10.51.2.255' | ||
} | ||
] | ||
} | ||
, { name: 'fw0', addresses: [] } | ||
, { name: 'en1', addresses: [] } | ||
, { name: 'lo0' | ||
, addresses: [ { addr: '127.0.0.1', netmask: '255.0.0.0' } ] | ||
, flags: 'PCAP_IF_LOOPBACK' | ||
} | ||
] | ||
### Deep decode of `curl nodejs.org`: | ||
Running `sys.inspect` on the first three decoded packets of this TCP session. | ||
First packet, TCP SYN: | ||
{ ethernet: | ||
{ dhost: '00:18:39:ff:f9:1c' | ||
, shost: '00:1f:5b:ce:3e:29' | ||
, ethertype: 2048 | ||
, ip: | ||
{ version: 4 | ||
, header_length: 5 | ||
, diffserv: 0 | ||
, total_length: 64 | ||
, identification: 49042 | ||
, flags: { reserved: 0, df: 1, mf: 0 } | ||
, fragment_offset: 0 | ||
, ttl: 64 | ||
, protocol: 6 | ||
, header_checksum: 35325 | ||
, saddr: '10.240.0.133' | ||
, daddr: '97.107.132.72' | ||
, protocol_name: 'TCP' | ||
, tcp: | ||
{ sport: 57230 | ||
, dport: 80 | ||
, seqno: 4179361823 | ||
, ackno: 1540242985 | ||
, data_offset: 11 | ||
, reserved: 0 | ||
, flags: | ||
{ cwr: 0 | ||
, ece: 0 | ||
, urg: 0 | ||
, ack: 0 | ||
, psh: 0 | ||
, rst: 0 | ||
, syn: 1 | ||
, fin: 0 | ||
} | ||
, window_size: 65535 | ||
, checksum: 2601 | ||
, urgent_pointer: 0 | ||
, payload_offset: 78 | ||
, payload: { length: 0 } | ||
} | ||
} | ||
} | ||
, pcap_header: | ||
{ time: Sat, 22 May 2010 07:48:40 GMT | ||
, tv_sec: 1274514520 | ||
, tv_usec: 820479 | ||
, caplen: 78 | ||
, len: 78 | ||
, link_type: 'LINKTYPE_ETHERNET' | ||
} | ||
} | ||
Second packet, TCP SYN+ACK: | ||
{ ethernet: | ||
{ dhost: '00:1f:5b:ce:3e:29' | ||
, shost: '00:18:39:ff:f9:1c' | ||
, ethertype: 2048 | ||
, ip: | ||
{ version: 4 | ||
, header_length: 5 | ||
, diffserv: 32 | ||
, total_length: 60 | ||
, identification: 0 | ||
, flags: { reserved: 0, df: 1, mf: 0 } | ||
, fragment_offset: 0 | ||
, ttl: 48 | ||
, protocol: 6 | ||
, header_checksum: 22900 | ||
, saddr: '97.107.132.72' | ||
, daddr: '10.240.0.133' | ||
, protocol_name: 'TCP' | ||
, tcp: | ||
{ sport: 80 | ||
, dport: 57230 | ||
, seqno: 1042874392 | ||
, ackno: 973076764 | ||
, data_offset: 10 | ||
, reserved: 0 | ||
, flags: | ||
{ cwr: 0 | ||
, ece: 0 | ||
, urg: 0 | ||
, ack: 1 | ||
, psh: 0 | ||
, rst: 0 | ||
, syn: 1 | ||
, fin: 0 | ||
} | ||
, window_size: 5792 | ||
, checksum: 35930 | ||
, urgent_pointer: 0 | ||
, payload_offset: 74 | ||
, payload: { length: 0 } | ||
} | ||
} | ||
} | ||
, pcap_header: | ||
{ time: Sat, 22 May 2010 07:48:40 GMT | ||
, tv_sec: 1274514520 | ||
, tv_usec: 915980 | ||
, caplen: 74 | ||
, len: 74 | ||
, link_type: 'LINKTYPE_ETHERNET' | ||
} | ||
} | ||
Third packet, TCP ACK, 3-way handshake is now complete: | ||
{ ethernet: | ||
{ dhost: '00:18:39:ff:f9:1c' | ||
, shost: '00:1f:5b:ce:3e:29' | ||
, ethertype: 2048 | ||
, ip: | ||
{ version: 4 | ||
, header_length: 5 | ||
, diffserv: 0 | ||
, total_length: 52 | ||
, identification: 39874 | ||
, flags: { reserved: 0, df: 1, mf: 0 } | ||
, fragment_offset: 0 | ||
, ttl: 64 | ||
, protocol: 6 | ||
, header_checksum: 44505 | ||
, saddr: '10.240.0.133' | ||
, daddr: '97.107.132.72' | ||
, protocol_name: 'TCP' | ||
, tcp: | ||
{ sport: 57230 | ||
, dport: 80 | ||
, seqno: 4179361823 | ||
, ackno: 1540242985 | ||
, data_offset: 8 | ||
, reserved: 0 | ||
, flags: | ||
{ cwr: 0 | ||
, ece: 0 | ||
, urg: 0 | ||
, ack: 1 | ||
, psh: 0 | ||
, rst: 0 | ||
, syn: 0 | ||
, fin: 0 | ||
} | ||
, window_size: 65535 | ||
, checksum: 53698 | ||
, urgent_pointer: 0 | ||
, payload_offset: 66 | ||
, payload: { length: 0 } | ||
} | ||
} | ||
} | ||
, pcap_header: | ||
{ time: Sat, 22 May 2010 07:48:40 GMT | ||
, tv_sec: 1274514520 | ||
, tv_usec: 916054 | ||
, caplen: 66 | ||
, len: 66 | ||
, link_type: 'LINKTYPE_ETHERNET' | ||
} | ||
} | ||
## Help Wanted | ||
I want to build up decoders and printers for all popular protocols. Patches are welcome. | ||
## LICENSE - "MIT License" | ||
@@ -475,0 +201,0 @@ |
@@ -112,4 +112,4 @@ var EventEmitter = require("events").EventEmitter; | ||
this.send_next_seq = tcp.seqno + 1; | ||
this.send_bytes_ip = ip.header_bytes; | ||
this.send_bytes_tcp = tcp.header_bytes; | ||
this.send_bytes_ip = ip.headerLength; | ||
this.send_bytes_tcp = tcp.headerLength; | ||
} else if (tcp.flags.syn && !tcp.flags.ack) { | ||
@@ -128,4 +128,4 @@ this.emit("syn retry", this); | ||
if (src === this.dst && tcp.flags.syn && tcp.flags.ack) { | ||
this.recv_bytes_ip += ip.header_bytes; | ||
this.recv_bytes_tcp += tcp.header_bytes; | ||
this.recv_bytes_ip += ip.headerLength; | ||
this.recv_bytes_tcp += tcp.headerLength; | ||
this.recv_packets[tcp.seqno + 1] = this.current_cap_time; | ||
@@ -150,4 +150,4 @@ this.recv_acks[tcp.ackno] = this.current_cap_time; | ||
if (src === this.src && tcp.flags.ack) { // TODO - make sure SYN flag isn't set, also match src and dst | ||
this.send_bytes_ip += ip.header_bytes; | ||
this.send_bytes_tcp += tcp.header_bytes; | ||
this.send_bytes_ip += ip.headerLength; | ||
this.send_bytes_tcp += tcp.headerLength; | ||
this.send_acks[tcp.ackno] = this.current_cap_time; | ||
@@ -175,11 +175,11 @@ this.connect_time = this.current_cap_time; | ||
if (src === this.src) { // this packet came from the active opener / client | ||
this.send_bytes_ip += ip.header_bytes; | ||
this.send_bytes_tcp += tcp.header_bytes; | ||
if (tcp.data_bytes) { | ||
if (this.send_packets[tcp.seqno + tcp.data_bytes]) { | ||
this.emit("retransmit", this, "send", tcp.seqno + tcp.data_bytes); | ||
if (this.send_retrans[tcp.seqno + tcp.data_bytes]) { | ||
this.send_retrans[tcp.seqno + tcp.data_bytes] += 1; | ||
this.send_bytes_ip += ip.headerLength; | ||
this.send_bytes_tcp += tcp.headerLength; | ||
if (tcp.dataLength > 0) { | ||
if (this.send_packets[tcp.seqno + tcp.dataLength]) { | ||
this.emit("retransmit", this, "send", tcp.seqno + tcp.dataLength); | ||
if (this.send_retrans[tcp.seqno + tcp.dataLength]) { | ||
this.send_retrans[tcp.seqno + tcp.dataLength] += 1; | ||
} else { | ||
this.send_retrans[tcp.seqno + tcp.data_bytes] = 1; | ||
this.send_retrans[tcp.seqno + tcp.dataLength] = 1; | ||
} | ||
@@ -189,4 +189,4 @@ } else { | ||
} | ||
this.send_bytes_payload += tcp.data_bytes; | ||
this.send_packets[tcp.seqno + tcp.data_bytes] = this.current_cap_time; | ||
this.send_bytes_payload += tcp.dataLength; | ||
this.send_packets[tcp.seqno + tcp.dataLength] = this.current_cap_time; | ||
} | ||
@@ -201,11 +201,11 @@ if (this.recv_packets[tcp.ackno]) { | ||
} else if (src === this.dst) { // this packet came from the passive opener / server | ||
this.recv_bytes_ip += ip.header_bytes; | ||
this.recv_bytes_tcp += tcp.header_bytes; | ||
if (tcp.data_bytes) { | ||
if (this.recv_packets[tcp.seqno + tcp.data_bytes]) { | ||
this.emit("retransmit", this, "recv", tcp.seqno + tcp.data_bytes); | ||
if (this.recv_retrans[tcp.seqno + tcp.data_bytes]) { | ||
this.recv_retrans[tcp.seqno + tcp.data_bytes] += 1; | ||
this.recv_bytes_ip += ip.headerLength; | ||
this.recv_bytes_tcp += tcp.headerLength; | ||
if (tcp.dataLength > 0) { | ||
if (this.recv_packets[tcp.seqno + tcp.dataLength]) { | ||
this.emit("retransmit", this, "recv", tcp.seqno + tcp.dataLength); | ||
if (this.recv_retrans[tcp.seqno + tcp.dataLength]) { | ||
this.recv_retrans[tcp.seqno + tcp.dataLength] += 1; | ||
} else { | ||
this.recv_retrans[tcp.seqno + tcp.data_bytes] = 1; | ||
this.recv_retrans[tcp.seqno + tcp.dataLength] = 1; | ||
} | ||
@@ -215,4 +215,4 @@ } else { | ||
} | ||
this.recv_bytes_payload += tcp.data_bytes; | ||
this.recv_packets[tcp.seqno + tcp.data_bytes] = this.current_cap_time; | ||
this.recv_bytes_payload += tcp.dataLength; | ||
this.recv_packets[tcp.seqno + tcp.dataLength] = this.current_cap_time; | ||
} | ||
@@ -281,3 +281,3 @@ if (this.send_packets[tcp.ackno]) { | ||
TCPSession.prototype.CLOSED = function (packet) { | ||
TCPSession.prototype.CLOSED = function (/*packet*/) { | ||
// not sure what to do here. We are closed, so I guess bump some counters or something. | ||
@@ -284,0 +284,0 @@ }; |
@@ -8,8 +8,2 @@ function lpad(str, len) { | ||
exports.dump_bytes = function dump_bytes(raw_packet, offset) { | ||
for (var i = offset; i < raw_packet.pcap_header.caplen ; i += 1) { | ||
console.log(i + ": " + raw_packet[i]); | ||
} | ||
}; | ||
var int8_to_hex = []; | ||
@@ -16,0 +10,0 @@ var int8_to_hex_nopad = []; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
71
172285
11
3274
213
4
+ Addednan@2.20.0(transitive)
- Removednan@1.6.2(transitive)
Updatednan@^2.0.9
Updatedsocketwatcher@git+https://github.com/bytzdev/node-socketwatcher.git