-
Notifications
You must be signed in to change notification settings - Fork 257
Expand file tree
/
Copy pathipv4.js
More file actions
125 lines (99 loc) · 3.26 KB
/
ipv4.js
File metadata and controls
125 lines (99 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
var IPv4Addr = require("./ipv4_addr");
var protocols = require("./ip_protocols");
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 () {
var ret = "[";
if (this.reserved) {
ret += "r";
}
if (this.doNotFragment) {
ret += "d";
}
if (this.moreFragments) {
ret += "m";
}
ret += "]";
return ret;
};
function IPv4(emitter, logger) {
this.emitter = emitter;
this.logger = logger;
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;
}
// http://en.wikipedia.org/wiki/IPv4
IPv4.prototype.decode = function (raw_packet, offset) {
var orig_offset = offset;
this.version = (raw_packet[offset] & 0xf0) >> 4;
this.headerLength = (raw_packet[offset] & 0x0f) << 2;
offset += 1;
this.diffserv = raw_packet[offset];
offset += 1;
this.length = raw_packet.readUInt16BE(offset, true);
offset += 2;
this.identification = raw_packet.readUInt16BE(offset, true);
offset += 2;
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.headerChecksum = raw_packet.readUInt16BE(offset, true);
offset += 2;
this.saddr = new IPv4Addr(this.emitter).decode(raw_packet, offset);
offset += 4;
this.daddr = new IPv4Addr(this.emitter).decode(raw_packet, offset);
offset += 4;
// TODO - parse IP "options" if header_length > 5
offset = orig_offset + this.headerLength;
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 flags = this.flags.toString();
if (flags.length > 2) {
ret += "flags " + flags + " ";
}
if(this.payload === undefined || this.payload === null ){
ret += "proto " + this.protocol;
} else {
ret += this.payload.constructor.name;
}
return ret + " " + this.payload;
};
module.exports = IPv4;