node-netlink 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/native/netlink.cc DELETED
@@ -1,360 +0,0 @@
1
- #include <node.h>
2
- #include <nan.h>
3
- #include <node_object_wrap.h>
4
-
5
- #include <sys/types.h>
6
- #include <sys/socket.h>
7
-
8
- #include <linux/netlink.h>
9
- #include <linux/rtnetlink.h>
10
-
11
- #include <uv.h>
12
- #include <unistd.h>
13
-
14
- static void alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) {
15
- buf->base = (char*) malloc(suggested_size);
16
- buf->len = suggested_size;
17
- }
18
-
19
- class NetlinkSocket : public node::ObjectWrap {
20
- public:
21
- static void Init(v8::Local<v8::Object> exports);
22
-
23
- private:
24
- explicit NetlinkSocket(v8::Isolate* isolate, int family, int pid, v8::Local<v8::Function> listener);
25
- ~NetlinkSocket();
26
-
27
- static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
28
- static void Send(const v8::FunctionCallbackInfo<v8::Value>& args);
29
- static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
30
- static v8::Persistent<v8::Function> constructor;
31
-
32
- static void onRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags);
33
- static void onSent(uv_udp_send_t* req, int status);
34
-
35
- int fd;
36
- uint32_t nl_pid;
37
- uv_udp_t udp_handle;
38
- v8::Global<v8::Function> listener;
39
- };
40
-
41
- v8::Persistent<v8::Function> NetlinkSocket::constructor;
42
-
43
- NetlinkSocket::NetlinkSocket(v8::Isolate* isolate, int family, int pid, v8::Local<v8::Function> listener) {
44
- fd = socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, family);
45
- if(fd < 0) {
46
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to create socket")));
47
- return;
48
- }
49
-
50
- struct sockaddr_nl src_addr;
51
- memset(&src_addr, 0, sizeof(src_addr));
52
- src_addr.nl_family = AF_NETLINK;
53
- src_addr.nl_pid = pid;
54
- src_addr.nl_groups = 0;
55
-
56
- int res;
57
-
58
- res = bind(fd, (struct sockaddr*) &src_addr, sizeof(src_addr));
59
- if(res < 0) {
60
- close(fd);
61
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to bind socket")));
62
- return;
63
- }
64
-
65
- if(src_addr.nl_pid == 0) {
66
- socklen_t length = sizeof(src_addr);
67
-
68
- struct sockaddr_nl act_addr;
69
-
70
- res = getsockname(fd, (struct sockaddr*) &act_addr, &length);
71
- if(res < 0) {
72
- close(fd);
73
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to get assigned socket address")));
74
- return;
75
- }
76
-
77
- nl_pid = act_addr.nl_pid;
78
- } else {
79
- nl_pid = src_addr.nl_pid;
80
- }
81
-
82
- res = uv_udp_init(uv_default_loop(), &udp_handle);
83
- if(res != 0) {
84
- close(fd);
85
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to init udp handle")));
86
- return;
87
- }
88
-
89
- uv_handle_set_data((uv_handle_t*) &udp_handle, this);
90
-
91
- res = uv_udp_open(&udp_handle, fd);
92
- if(res != 0) {
93
- close(fd);
94
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to create udp handle")));
95
- return;
96
- }
97
-
98
- res = uv_udp_recv_start(&udp_handle, alloc_cb, NetlinkSocket::onRecv);
99
- if(res != 0) {
100
- close(fd);
101
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to start udp receive")));
102
- return;
103
- }
104
-
105
- this->listener = v8::Global<v8::Function>(isolate, listener);
106
- }
107
-
108
- NetlinkSocket::~NetlinkSocket() {
109
- }
110
-
111
- void NetlinkSocket::Init(v8::Local<v8::Object> exports) {
112
- v8::Isolate* isolate = exports->GetIsolate();
113
-
114
- v8::Local<v8::FunctionTemplate> tpl = v8::FunctionTemplate::New(isolate, New);
115
- tpl->SetClassName(v8::String::NewFromUtf8(isolate, "NetlinkSocket"));
116
- tpl->InstanceTemplate()->SetInternalFieldCount(1);
117
-
118
- NODE_SET_PROTOTYPE_METHOD(tpl, "send", Send);
119
- NODE_SET_PROTOTYPE_METHOD(tpl, "close", Close);
120
-
121
- constructor.Reset(isolate, tpl->GetFunction());
122
- exports->Set(v8::String::NewFromUtf8(isolate, "NetlinkSocket"),
123
- tpl->GetFunction());
124
- }
125
-
126
- void NetlinkSocket::New(const v8::FunctionCallbackInfo<v8::Value>& args) {
127
- v8::Isolate* isolate = args.GetIsolate();
128
-
129
- if (args.IsConstructCall()) {
130
- int family = args[0]->IsUndefined() ? 0 : args[0]->Int32Value();
131
- int pid = args[1]->IsUndefined() ? 0 : args[1]->Int32Value();
132
- v8::Local<v8::Function> listener = v8::Local<v8::Function>::Cast(args[1]);
133
- NetlinkSocket* obj = new NetlinkSocket(isolate, family, pid, listener);
134
- obj->Wrap(args.This());
135
- args.GetReturnValue().Set(args.This());
136
- } else {
137
- const int argc = 1;
138
- v8::Local<v8::Value> argv[argc] = { args[0] };
139
- v8::Local<v8::Context> context = isolate->GetCurrentContext();
140
- v8::Local<v8::Function> cons = v8::Local<v8::Function>::New(isolate, constructor);
141
- v8::Local<v8::Object> result =
142
- cons->NewInstance(context, argc, argv).ToLocalChecked();
143
- args.GetReturnValue().Set(result);
144
- }
145
- }
146
-
147
- struct send_work_data {
148
- v8::Isolate* isolate;
149
- v8::Global<v8::Context> ctx;
150
- v8::Global<v8::Function> cb;
151
-
152
- uint8_t* buf;
153
- size_t len;
154
- };
155
-
156
- void NetlinkSocket::onRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) {
157
- NetlinkSocket* socket = reinterpret_cast<NetlinkSocket*>(uv_handle_get_data((uv_handle_t*) handle));
158
-
159
- int len;
160
- struct nlmsghdr *nh;
161
-
162
- int part_count = 0;
163
-
164
- len = nread;
165
- for (nh = (struct nlmsghdr *) buf->base; NLMSG_OK (nh, len);
166
- nh = NLMSG_NEXT (nh, len)) {
167
- part_count += 1;
168
- }
169
-
170
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
171
- v8::HandleScope scope(isolate);
172
-
173
- auto result = v8::Array::New(isolate);
174
-
175
- int idx = 0;
176
- len = nread;
177
- for (nh = (struct nlmsghdr *) buf->base; NLMSG_OK (nh, len);
178
- nh = NLMSG_NEXT (nh, len)) {
179
-
180
- auto part = v8::Object::New(isolate);
181
-
182
- auto header = v8::Object::New(isolate);
183
- header->Set(v8::String::NewFromUtf8(isolate, "nlmsg_len"), v8::Integer::New(isolate, nh->nlmsg_len));
184
- header->Set(v8::String::NewFromUtf8(isolate, "nlmsg_type"), v8::Integer::New(isolate, nh->nlmsg_type));
185
- header->Set(v8::String::NewFromUtf8(isolate, "nlmsg_flags"), v8::Integer::New(isolate, nh->nlmsg_flags));
186
- header->Set(v8::String::NewFromUtf8(isolate, "nlmsg_seq"), v8::Integer::New(isolate, nh->nlmsg_seq));
187
- header->Set(v8::String::NewFromUtf8(isolate, "nlmsg_pid"), v8::Integer::New(isolate, nh->nlmsg_pid));
188
-
189
- auto payload = Nan::CopyBuffer((const char*) NLMSG_DATA(nh), NLMSG_PAYLOAD(nh, 0)).ToLocalChecked();
190
-
191
- part->Set(v8::String::NewFromUtf8(isolate, "header"), header);
192
- part->Set(v8::String::NewFromUtf8(isolate, "payload"), payload);
193
-
194
- result->Set(idx, part);
195
- idx += 1;
196
- }
197
-
198
- v8::Local<v8::Value> argv[] = { result };
199
-
200
- v8::Local<v8::Object> dummy = v8::Object::New(isolate);
201
- v8::Local<v8::Function> cb = v8::Local<v8::Function>::New(isolate, socket->listener);
202
-
203
- Nan::AsyncResource("netlink:recv").runInAsyncScope(dummy, cb, 1, argv);
204
- }
205
-
206
- void NetlinkSocket::onSent(uv_udp_send_t* req, int status) {
207
- struct send_work_data* data = reinterpret_cast<struct send_work_data*>(uv_handle_get_data((uv_handle_t*) req));
208
-
209
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
210
-
211
- v8::HandleScope scope(isolate);
212
-
213
- v8::Local<v8::Value> argv[] = { v8::Integer::New(isolate, status) };
214
-
215
- v8::Local<v8::Function> cb = v8::Local<v8::Function>::New(isolate, data->cb);
216
-
217
- v8::Local<v8::Object> dummy = v8::Object::New(isolate);
218
- Nan::AsyncResource("netlink:send").runInAsyncScope(dummy, cb, 1, argv);
219
-
220
- delete data->buf;
221
- delete data;
222
- delete req;
223
- }
224
-
225
- extern "C" int uv__udp_send(uv_udp_send_t* req,
226
- uv_udp_t* handle,
227
- const uv_buf_t bufs[],
228
- unsigned int nbufs,
229
- const struct sockaddr* addr,
230
- unsigned int addrlen,
231
- uv_udp_send_cb send_cb);
232
-
233
- void NetlinkSocket::Send(const v8::FunctionCallbackInfo<v8::Value>& args) {
234
- v8::Isolate* isolate = args.GetIsolate();
235
-
236
- NetlinkSocket* obj = ObjectWrap::Unwrap<NetlinkSocket>(args.Holder());
237
-
238
- struct nlmsghdr hdr;
239
- memset(&hdr, 0, sizeof(hdr));
240
-
241
- v8::Local<v8::Function> hdl = v8::Local<v8::Function>::Cast(args[3]);
242
-
243
- auto header = args[0]->ToObject();
244
- auto nlmsg_len = header->Get(v8::String::NewFromUtf8(isolate, "nlmsg_len"));
245
- auto nlmsg_type = header->Get(v8::String::NewFromUtf8(isolate, "nlmsg_type"));
246
- auto nlmsg_flags = header->Get(v8::String::NewFromUtf8(isolate, "nlmsg_flags"));
247
- auto nlmsg_seq = header->Get(v8::String::NewFromUtf8(isolate, "nlmsg_seq"));
248
- auto nlmsg_pid = header->Get(v8::String::NewFromUtf8(isolate, "nlmsg_pid"));
249
-
250
- if(!nlmsg_len->IsUndefined()) {
251
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_len cannot be set as it is generated")));
252
- return;
253
- }
254
-
255
- if(nlmsg_type->IsUndefined()) {
256
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_type is mandatory in header")));
257
- return;
258
- } else if(!nlmsg_type->IsUint32()) {
259
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_type must be an unsigned integer")));
260
- return;
261
- } else {
262
- auto value = nlmsg_type->ToUint32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
263
- if(value > 0xFFFF) {
264
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_type must not exceed 16 bit range")));
265
- return;
266
- }
267
- hdr.nlmsg_type = value;
268
- }
269
-
270
- if(nlmsg_flags->IsUndefined()) {
271
- hdr.nlmsg_flags = 0;
272
- } else if(!nlmsg_flags->IsUint32()) {
273
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_flags must be an unsigned integer")));
274
- return;
275
- } else {
276
- auto value = nlmsg_flags->ToUint32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
277
- if(value > 0xFFFF) {
278
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_flags must not exceed 16 bit range")));
279
- return;
280
- }
281
- hdr.nlmsg_flags = value;
282
- }
283
-
284
- if(nlmsg_seq->IsUndefined()) {
285
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_seq is mandatory in header")));
286
- return;
287
- } else if(!nlmsg_seq->IsUint32()) {
288
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_seq must be an unsigned integer")));
289
- return;
290
- } else {
291
- auto value = nlmsg_seq->ToUint32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
292
- if(value > 0xFFFFFFFF) {
293
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_seq must not exceed 32 bit range")));
294
- return;
295
- }
296
- hdr.nlmsg_seq = value;
297
- }
298
-
299
- if(nlmsg_flags->IsUndefined()) {
300
- hdr.nlmsg_pid = obj->nl_pid;
301
- } else if(!nlmsg_flags->IsUint32()) {
302
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_flags must be an unsigned integer")));
303
- return;
304
- } else {
305
- auto value = nlmsg_pid->ToUint32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
306
- if(value > 0xFFFFFFFF) {
307
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "nlmsg_flags must not exceed 32 bit range")));
308
- return;
309
- }
310
- hdr.nlmsg_pid = value;
311
- }
312
-
313
- uv_udp_send_t* send_req = new uv_udp_send_t();
314
- memset(send_req, 0, sizeof(uv_udp_send_t));
315
-
316
- struct sockaddr_nl dst_addr;
317
- memset(&dst_addr, 0, sizeof(dst_addr));
318
- dst_addr.nl_family = AF_NETLINK;
319
- dst_addr.nl_pid = 0;
320
- dst_addr.nl_groups = 0;
321
-
322
- v8::Local<v8::Object> payload = v8::Local<v8::Object>::Cast(args[1]);
323
-
324
- hdr.nlmsg_len = NLMSG_LENGTH(node::Buffer::Length(payload));
325
-
326
- struct send_work_data* data = new send_work_data();
327
- data->len = sizeof(hdr) + node::Buffer::Length(payload);
328
- data->buf = new uint8_t[data->len];
329
- memcpy(data->buf + 0, &hdr, sizeof(hdr));
330
- memcpy(data->buf + sizeof(hdr), node::Buffer::Data(payload), node::Buffer::Length(payload));
331
-
332
- uv_buf_t bufs[1];
333
- bufs[0].base = (char*) data->buf;
334
- bufs[0].len = data->len;
335
-
336
- int res;
337
-
338
- data->isolate = isolate;
339
- data->ctx = v8::Global<v8::Context>(isolate, isolate->GetCurrentContext());
340
- data->cb = v8::Global<v8::Function>(isolate, hdl);
341
-
342
- uv_handle_set_data((uv_handle_t*) send_req, data);
343
-
344
- res = uv__udp_send(send_req, &obj->udp_handle, bufs, sizeof(bufs) / sizeof(bufs[0]), (struct sockaddr*) &dst_addr, sizeof(dst_addr), NetlinkSocket::onSent);
345
- if(res < 0) {
346
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "failed to send packet")));
347
- return;
348
- }
349
- }
350
-
351
- void NetlinkSocket::Close(const v8::FunctionCallbackInfo<v8::Value>& args) {
352
- NetlinkSocket* obj = ObjectWrap::Unwrap<NetlinkSocket>(args.Holder());
353
-
354
- uv_udp_recv_stop(&obj->udp_handle);
355
-
356
- close(obj->fd);
357
- obj->fd = -1;
358
- }
359
-
360
- NODE_MODULE(netlink, NetlinkSocket::Init)