1212#include " pcap_session.h"
1313
1414using namespace v8 ;
15+ using Nan::Callback;
16+ using Nan::AsyncQueueWorker;
17+ using Nan::AsyncWorker;
18+ using Nan::Callback;
19+ using Nan::HandleScope;
20+ using Nan::New;
21+ using Nan::Null;
22+ using Nan::To;
23+
24+ class PcapWorker : public AsyncWorker {
25+ public:
26+ PcapWorker (
27+ Callback *callback,
28+ std::string device,
29+ std::string filter,
30+ int buffer_size,
31+ std::string pcap_output_filename,
32+ int num_packets
33+ )
34+ :
35+ AsyncWorker (callback),
36+ device (device),
37+ filter (filter),
38+ buffer_size (buffer_size),
39+ pcap_output_filename (pcap_output_filename),
40+ num_packets (num_packets)
41+ {}
42+ ~PcapWorker () {}
43+
44+ // Executed inside the worker-thread.
45+ // It is not safe to access V8, or V8 data structures
46+ // here, so everything we need for input and output
47+ // should go on `this`.
48+ void Execute () {
49+ if (pcap_lookupnet (device.c_str (), &net, &mask, errbuf) == -1 ) {
50+ net = 0 ;
51+ mask = 0 ;
52+ fprintf (stderr, " warning: %s - this may not actually work\n " , errbuf);
53+ SetErrorMessage (errbuf);
54+ return ;
55+ }
56+ pcap_handle = pcap_create (device.c_str (), errbuf);
57+ if (pcap_handle == NULL ) {
58+ SetErrorMessage (errbuf);
59+ return ;
60+ }
61+
62+ // 64KB is the max IPv4 packet size
63+ if (pcap_set_snaplen (pcap_handle, 65535 ) != 0 ) {
64+ SetErrorMessage (" error setting snaplen" );
65+ return ;
66+ }
67+
68+ // always use promiscuous mode
69+ if (pcap_set_promisc (pcap_handle, 1 ) != 0 ) {
70+ SetErrorMessage (" error setting promiscuous mode" );
71+ return ;
72+ }
73+
74+ // Try to set buffer size. Sometimes the OS has a lower limit that it will silently enforce.
75+ if (pcap_set_buffer_size (pcap_handle, buffer_size) != 0 ) {
76+ SetErrorMessage (" error setting buffer size" );
77+ return ;
78+ }
79+
80+
81+ // set "timeout" on read, even though we are also setting nonblock below. On Linux this is required.
82+ if (pcap_set_timeout (pcap_handle, 1000 ) != 0 ) {
83+ SetErrorMessage (" error setting read timeout" );
84+ return ;
85+ }
86+
87+ if (pcap_activate (pcap_handle) != 0 ) {
88+ SetErrorMessage (pcap_geterr (pcap_handle));
89+ return ;
90+ }
91+ if ((pcap_output_filename.size ()) > 0 ) {
92+ pcap_dump_handle = pcap_dump_open (pcap_handle,pcap_output_filename.c_str ());
93+ if (pcap_dump_handle == NULL ) {
94+ SetErrorMessage (" error opening dump" );
95+ return ;
96+ }
97+ }
98+
99+
100+ if (filter.size () != 0 ) {
101+ if (pcap_compile (pcap_handle, &fp, filter.c_str (), 1 , net) == -1 ) {
102+ SetErrorMessage (pcap_geterr (pcap_handle));
103+ return ;
104+ }
105+
106+ if (pcap_setfilter (pcap_handle, &fp) == -1 ) {
107+ SetErrorMessage (pcap_geterr (pcap_handle));
108+ return ;
109+ }
110+
111+ pcap_loop (pcap_handle, num_packets, OnPacketReady, (unsigned char *)pcap_dump_handle);
112+ pcap_freecode (&fp);
113+ /*
114+ * Close the savefile opened in pcap_dump_open().
115+ */
116+ pcap_dump_close (pcap_dump_handle);
117+ /*
118+ * Close the packet capture device and free the memory used by the
119+ * packet capture descriptor.
120+ */
121+ pcap_close (pcap_handle);
122+ }
123+ }
124+
125+ // Executed when the async work is complete
126+ // this function will be run inside the main event loop
127+ // so it is safe to use V8 again
128+ void HandleOKCallback () {
129+
130+ Nan::HandleScope scope;
131+
132+ Local<Value> argv[] = {
133+ Nan::Null ()
134+ , New<Number>(num_packets)
135+ };
136+
137+ callback->Call (2 , argv);
138+ }
139+
140+
141+
142+ static void OnPacketReady (u_char *s, const struct pcap_pkthdr * pkthdr, const u_char* packet) {
143+ pcap_dump (s, pkthdr, packet);
144+ }
145+
146+ private:
147+
148+ std::string device;
149+ std::string filter;
150+ int buffer_size;
151+ std::string pcap_output_filename;
152+ int num_packets;
153+ struct bpf_program fp;
154+ bpf_u_int32 mask;
155+ bpf_u_int32 net;
156+ pcap_t *pcap_handle;
157+ pcap_dumper_t *pcap_dump_handle;
158+ char errbuf[PCAP_ERRBUF_SIZE];
159+
160+
161+
162+
163+ };
164+
15165
16166// Helper method, convert a sockaddr* (AF_INET or AF_INET6) to a string, and set it as the property
17167// named 'key' in the Address object you pass in.
@@ -135,6 +285,57 @@ NAN_METHOD(LibVersion)
135285 info.GetReturnValue ().Set (Nan::New (pcap_lib_version ()).ToLocalChecked ());
136286}
137287
288+ // Asynchronous access to the `Estimate()` function
289+ NAN_METHOD (PcapDumpAsync) {
290+
291+ if (info.Length () == 8 ) {
292+ if (!info[0 ]->IsString ()) {
293+ Nan::ThrowTypeError (" pcap Open: info[0] must be a String" );
294+ return ;
295+ }
296+ if (!info[1 ]->IsString ()) {
297+ Nan::ThrowTypeError (" pcap Open: info[1] must be a String" );
298+ return ;
299+ }
300+ if (!info[2 ]->IsInt32 ()) {
301+ Nan::ThrowTypeError (" pcap Open: info[2] must be a Number" );
302+ return ;
303+ }
304+ if (!info[3 ]->IsString ()) {
305+ Nan::ThrowTypeError (" pcap Open: info[3] must be a String" );
306+ return ;
307+ }
308+ if (!info[4 ]->IsFunction ()) {
309+ Nan::ThrowTypeError (" pcap Open: info[4] must be a Function" );
310+ return ;
311+ }
312+ if (!info[5 ]->IsBoolean ()) {
313+ Nan::ThrowTypeError (" pcap Open: info[5] must be a Boolean" );
314+ return ;
315+ }
316+ if (!info[6 ]->IsInt32 ()) {
317+ Nan::ThrowTypeError (" pcap Open: info[6] must be a Number" );
318+ return ;
319+ }
320+ if (!info[7 ]->IsFunction ()) {
321+ Nan::ThrowTypeError (" pcap Open: info[7] must be a Function" );
322+ return ;
323+ }
324+ } else {
325+ Nan::ThrowTypeError (" pcap CreatePcapDump: expecting 7 arguments" );
326+ return ;
327+ }
328+ Nan::Utf8String device (info[0 ]->ToString ());
329+ Nan::Utf8String filter (info[1 ]->ToString ());
330+ int buffer_size = info[2 ]->Int32Value ();
331+ Nan::Utf8String pcap_output_filename (info[3 ]->ToString ());
332+ int num_packets = info[6 ]->Int32Value ();
333+ Callback *callback = new Callback (info[7 ].As <Function>());
334+
335+ AsyncQueueWorker (new PcapWorker (callback, std::string (*device),std::string (*filter),buffer_size, std::string (*pcap_output_filename),num_packets));
336+ }
337+
338+
138339void Initialize (Handle<Object> exports)
139340{
140341 Nan::HandleScope scope;
@@ -144,6 +345,7 @@ void Initialize(Handle<Object> exports)
144345 exports->Set (Nan::New (" findalldevs" ).ToLocalChecked (), Nan::New<FunctionTemplate>(FindAllDevs)->GetFunction ());
145346 exports->Set (Nan::New (" default_device" ).ToLocalChecked (), Nan::New<FunctionTemplate>(DefaultDevice)->GetFunction ());
146347 exports->Set (Nan::New (" lib_version" ).ToLocalChecked (), Nan::New<FunctionTemplate>(LibVersion)->GetFunction ());
348+ exports->Set (Nan::New (" create_pcap_dump_async" ).ToLocalChecked (), Nan::New<FunctionTemplate>(PcapDumpAsync)->GetFunction ());
147349}
148350
149351NODE_MODULE (pcap_binding, Initialize)
0 commit comments