This repository was archived by the owner on Nov 8, 2024. It is now read-only.
forked from frankie-zeng/node_npcap
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnpcap_binding.cpp
More file actions
154 lines (128 loc) · 5.44 KB
/
npcap_binding.cpp
File metadata and controls
154 lines (128 loc) · 5.44 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "npcap_session.h"
#include <winsock2.h>
static void init_npcap_dll_path(napi_env env)
{
BOOL(WINAPI *SetDllDirectory)(LPCTSTR);
char sysdir_name[512];
int len;
SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
if (SetDllDirectory == NULL) {
Napi::TypeError::New(env, "Error in SetDllDirectory").ThrowAsJavaScriptException();
}
else {
len = GetSystemDirectory(sysdir_name, 480); // be safe
if (!len)
Napi::TypeError::New(env, "Error in GetSystemDirectory").ThrowAsJavaScriptException();
// error("Error in GetSystemDirectory (%d)", GetLastError());
strcat(sysdir_name, "\\Npcap");
if (SetDllDirectory(sysdir_name) == 0)
Napi::TypeError::New(env, "Error in SetDllDirectory(\"System32\\Npcap\")").ThrowAsJavaScriptException();
}
}
// Helper method, convert a sockaddr* (AF_INET or AF_INET6) to a string, and set it as the property
// named 'key' in the Address object you pass in.
static void SetAddrStringHelper(const char* key, sockaddr *addr,napi_env env, Napi::Object Address){
if(key && addr){
char dst_addr[INET6_ADDRSTRLEN + 1] = {0};
char* src = 0;
socklen_t size = 0;
if(addr->sa_family == AF_INET){
struct sockaddr_in* saddr = (struct sockaddr_in*) addr;
src = (char*) &(saddr->sin_addr);
size = INET_ADDRSTRLEN;
}else{
struct sockaddr_in6* saddr6 = (struct sockaddr_in6*) addr;
src = (char*) &(saddr6->sin6_addr);
size = INET6_ADDRSTRLEN;
}
const char* address = inet_ntop(addr->sa_family, src, dst_addr, size);
if(address){
Address.Set(key,Napi::String::New(env,address));
}
}
}
Napi::String DefaultDevice(const Napi::CallbackInfo& info){
char errbuf[PCAP_ERRBUF_SIZE];
// Look up the first device with an address, pcap_lookupdev() just returns the first non-loopback device.
pcap_if_t *alldevs, *dev;
pcap_addr_t *addr;
bool found = false;
Napi::String devName;
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
Napi::TypeError::New(info.Env(), errbuf).ThrowAsJavaScriptException();
return Napi::String::New(info.Env(),errbuf);
}
if (alldevs == NULL) {
Napi::TypeError::New(info.Env(), "pcap_findalldevs didn't find any devs").ThrowAsJavaScriptException();
return Napi::String::New(info.Env(),"pcap_findalldevs didn't find any devs");
}
for (dev = alldevs; dev != NULL; dev = dev->next) {
if (dev->addresses != NULL && !(dev->flags & PCAP_IF_LOOPBACK)) {
for (addr = dev->addresses; addr != NULL; addr = addr->next) {
// TODO - include IPv6 addresses in DefaultDevice guess
// if (addr->addr->sa_family == AF_INET || addr->addr->sa_family == AF_INET6) {
if (addr->addr->sa_family == AF_INET) {
devName=Napi::String::New(info.Env(),dev->name);
found = true;
break;
}
}
if (found) {
break;
}
}
}
pcap_freealldevs(alldevs);
return devName;
}
Napi::Array FindAllDevs(const Napi::CallbackInfo& info){
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *alldevs, *cur_dev;
Napi::Array DevsArray=Napi::Array::New(info.Env());
if (pcap_findalldevs(&alldevs, errbuf) == -1 || alldevs == NULL) {
Napi::TypeError::New(info.Env(), errbuf).ThrowAsJavaScriptException();
return DevsArray;
}
int i = 0;
for (cur_dev = alldevs ; cur_dev != NULL ; cur_dev = cur_dev->next, i++) {
Napi::Object Dev = Napi::Object::New(info.Env());
Dev.Set("name",Napi::String::New(info.Env(),cur_dev->name));
if (cur_dev->description != NULL) {
Dev.Set("description",Napi::String::New(info.Env(),cur_dev->description));
}
Napi::Array AddrArray = Napi::Array::New(info.Env());
int j = 0;
for (pcap_addr_t *cur_addr = cur_dev->addresses ; cur_addr != NULL ; cur_addr = cur_addr->next, j++) {
if (cur_addr->addr){
int af = cur_addr->addr->sa_family;
if(af == AF_INET || af == AF_INET6){
Napi::Object Address = Napi::Object::New(info.Env());
SetAddrStringHelper("addr", cur_addr->addr,info.Env(), Address);
SetAddrStringHelper("netmask", cur_addr->netmask,info.Env(), Address);
SetAddrStringHelper("broadaddr", cur_addr->broadaddr, info.Env(), Address);
SetAddrStringHelper("dstaddr", cur_addr->dstaddr, info.Env(), Address);
AddrArray[j]=Address;
}
}
}
Dev.Set("addresses",AddrArray);
if (cur_dev->flags & PCAP_IF_LOOPBACK) {
Dev.Set("flags",Napi::String::New(info.Env(),"PCAP_IF_LOOPBACK"));
}
DevsArray[i]=Dev;
}
pcap_freealldevs(alldevs);
return DevsArray;
}
Napi::String LibVersion(const Napi::CallbackInfo& info){
return Napi::String::New(info.Env(),pcap_lib_version());
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
init_npcap_dll_path(env);
PcapSession::Init(env,exports);
exports.Set(Napi::String::New(env, "lib_version"),Napi::Function::New(env, LibVersion));
exports.Set(Napi::String::New(env, "default_device"),Napi::Function::New(env, DefaultDevice));
exports.Set(Napi::String::New(env, "findalldevs"),Napi::Function::New(env, FindAllDevs));
return exports;
}
NODE_API_MODULE(pcap_binding, Init)