forked from node-pcap/node_pcap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcap.js
128 lines (106 loc) · 3.91 KB
/
pcap.js
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
126
127
128
var util = require("util");
var events = require("events");
var binding = require("./build/Release/pcap_binding");
var SocketWatcher = require("socketwatcher").SocketWatcher;
var decode = require("./decode").decode;
var tcp_tracker = require("./tcp_tracker");
var DNSCache = require("./dns_cache");
var timers = require("timers");
exports.decode = decode;
exports.TCPTracker = tcp_tracker.TCPTracker;
exports.TCPSession = tcp_tracker.TCPSession;
exports.DNSCache = DNSCache;
function PcapSession(is_live, device_name, filter, buffer_size, outfile, is_monitor) {
this.is_live = is_live;
this.device_name = device_name;
this.filter = filter || "";
this.buffer_size = buffer_size;
this.outfile = outfile || "";
this.is_monitor = Boolean(is_monitor);
this.link_type = null;
this.fd = null;
this.opened = null;
this.buf = null;
this.header = null;
this.read_watcher = null;
this.empty_reads = 0;
this.packets_read = null;
this.session = new binding.PcapSession();
if (typeof this.buffer_size === "number" && !isNaN(this.buffer_size)) {
this.buffer_size = Math.round(this.buffer_size);
} else {
this.buffer_size = 10 * 1024 * 1024; // Default buffer size is 10MB
}
var self = this;
// called for each packet read by pcap
function packet_ready() {
self.on_packet_ready();
}
if (this.is_live) {
this.device_name = this.device_name || binding.default_device();
this.link_type = this.session.open_live(this.device_name, this.filter, this.buffer_size, this.outfile, packet_ready, this.is_monitor);
} else {
this.link_type = this.session.open_offline(this.device_name, this.filter, this.buffer_size, this.outfile, packet_ready, this.is_monitor);
}
this.fd = this.session.fileno();
this.opened = true;
this.buf = new Buffer(this.buffer_size || 65535);
this.header = new Buffer(16);
if (is_live) {
this.readWatcher = new SocketWatcher();
// readWatcher gets a callback when pcap has data to read. multiple packets may be readable.
this.readWatcher.callback = function pcap_read_callback() {
var packets_read = self.session.dispatch(self.buf, self.header);
if (packets_read < 1) {
this.empty_reads += 1;
}
};
this.readWatcher.set(this.fd, true, false);
this.readWatcher.start();
} else {
timers.setImmediate(function() {
var packets = 0;
do {
packets = self.session.dispatch(self.buf, self.header);
} while ( packets > 0 );
self.emit("complete");
});
}
events.EventEmitter.call(this);
}
util.inherits(PcapSession, events.EventEmitter);
exports.lib_version = binding.lib_version();
exports.findalldevs = function () {
return binding.findalldevs();
};
function PacketWithHeader(buf, header, link_type) {
this.buf = buf;
this.header = header;
this.link_type = link_type;
}
PcapSession.prototype.on_packet_ready = function () {
var full_packet = new PacketWithHeader(this.buf, this.header, this.link_type);
this.emit("packet", full_packet);
};
PcapSession.prototype.close = function () {
this.opened = false;
this.session.close();
if (this.is_live) {
this.readWatcher.stop();
}
// TODO - remove listeners so program will exit I guess?
};
PcapSession.prototype.stats = function () {
return this.session.stats();
};
PcapSession.prototype.inject = function (data) {
return this.session.inject(data);
};
exports.Pcap = PcapSession;
exports.PcapSession = PcapSession;
exports.createSession = function (device, filter, buffer_size, monitor) {
return new PcapSession(true, device, filter, buffer_size, null, monitor);
};
exports.createOfflineSession = function (path, filter) {
return new PcapSession(false, path, filter, 0, null, null);
};