node-netlink 0.0.3 → 0.0.5

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/lib/index.js DELETED
@@ -1,259 +0,0 @@
1
- import socket from "po6-socket";
2
- import EventEmitter from "events";
3
-
4
- import structures from "./structures.js";
5
- import netlinkParser from "./parser.js";
6
- import errorFactory from "./error.js";
7
-
8
- const AF_NETLINK = 16n;
9
- const SOCK_DGRAM = 2n;
10
-
11
- const NLM_F_ECHO = 8n;
12
- const NLM_F_REQUEST = 1n;
13
- const NLM_F_MULTI = 2n;
14
- const NLM_F_MATCH = 0x200n;
15
- const NLM_F_DUMP = 0x300n;
16
- const NLM_F_ACK = 4n;
17
- const NLM_F_CREATE = 0x400n;
18
- const NLM_F_EXCL = 0x200n;
19
-
20
- const NLMSG_ERROR = 2n;
21
- const NLMSG_DONE = 3n;
22
-
23
- const open = ({ family, pid, groups }) => {
24
- const emitter = new EventEmitter();
25
-
26
- return socket
27
- .create({
28
- domain: AF_NETLINK,
29
- type: SOCK_DGRAM,
30
- protocol: BigInt(family),
31
- })
32
- .then((sock) => {
33
- const netlinkAddress = structures.sockaddr_nl.format({
34
- nl_family: AF_NETLINK,
35
- nl_pid: BigInt(pid || 0),
36
- nl_groups: BigInt(groups || 0),
37
- });
38
-
39
- const close = () => {
40
- return sock.close();
41
- };
42
-
43
- sock.on("message", ({ data }) => {
44
- const parsedPackets = netlinkParser.parseMessage({ message: data });
45
-
46
- parsedPackets.forEach((packet) => {
47
- emitter.emit("message", packet);
48
- });
49
- });
50
-
51
- let seq = 1n;
52
-
53
- const send = ({ header: requestedHeader, payload }) => {
54
- let header = Object.assign({}, requestedHeader);
55
-
56
- if (header.nlmsg_seq === undefined) {
57
- header = Object.assign({}, header, {
58
- nlmsg_seq: seq,
59
- });
60
- seq += 1n;
61
- }
62
-
63
- if (header.nlmsg_pid === undefined) {
64
- header = Object.assign({}, header, {
65
- // "nlmsg_pid": nl_pid
66
- });
67
- }
68
-
69
- header = Object.assign({}, header, {
70
- nlmsg_len: BigInt(structures.nlmsghdr.size) + BigInt(payload.length),
71
- });
72
-
73
- const headerAsBuf = structures.nlmsghdr.format(header);
74
-
75
- const data = Buffer.concat([headerAsBuf, payload]);
76
-
77
- const destBuffer = structures.sockaddr_nl.format({
78
- nl_family: AF_NETLINK,
79
- });
80
-
81
- // TODO: flags
82
-
83
- return sock.sendmsg({
84
- data,
85
- msghdr: {
86
- msg_name: destBuffer,
87
- },
88
- });
89
- };
90
-
91
- let requested = {};
92
-
93
- const maybeAppendMessageToResponse = ({ message }) => {
94
- const { header } = message;
95
-
96
- if (header.nlmsg_type === NLMSG_DONE) {
97
- return;
98
- }
99
-
100
- requested = {
101
- [header.nlmsg_seq]: {
102
- ...requested[header.nlmsg_seq],
103
- msgs: [...(requested[header.nlmsg_seq]?.msgs || []), message],
104
- },
105
- };
106
- };
107
-
108
- const maybeFinishRequest = ({ message }) => {
109
- const { header } = message;
110
- const req = requested[header.nlmsg_seq];
111
-
112
- const isLast =
113
- header.nlmsg_type === NLMSG_ERROR || header.nlmsg_type === NLMSG_DONE;
114
-
115
- if (isLast) {
116
- clearTimeout(req.schedule);
117
- req.resolve(req.msgs);
118
-
119
- const { [header.nlmsg_seq]: unused, ...other } = requested;
120
- requested = other;
121
- }
122
- };
123
-
124
- const processResponse = ({ message }) => {
125
- const { header } = message;
126
- const req = requested[header.nlmsg_seq];
127
-
128
- if (!req) {
129
- console.warn(
130
- `could not find pending request for seq=${header.nlmsg_seq}`
131
- );
132
- console.warn(`nlmsg_type = ${header.nlmsg_type}`);
133
-
134
- return;
135
- }
136
-
137
- maybeAppendMessageToResponse({ message });
138
- maybeFinishRequest({ message });
139
- };
140
-
141
- emitter.on("message", (message) => {
142
- const { header } = message;
143
-
144
- if (header.nlmsg_flags & NLM_F_REQUEST) {
145
- return;
146
- }
147
-
148
- if (header.nlmsg_seq === 0) {
149
- return;
150
- }
151
-
152
- processResponse({ message });
153
- });
154
-
155
- const tryTalk = (message, { timeout = 10000 } = {}) => {
156
- if (!(message.header.nlmsg_flags & NLM_F_ACK)) {
157
- throw new Error(`talk only supports requests with NLM_F_ACK set`);
158
- }
159
-
160
- return Promise.resolve()
161
- .then(() => {
162
- return new Promise((resolve, reject) => {
163
- const header = Object.assign({}, message.header, {
164
- nlmsg_seq: seq,
165
- });
166
- seq += 1n;
167
-
168
- const schedule = setTimeout(() => {
169
- const { [header.nlmsg_seq]: unused, ...other } = requested;
170
- requested = other;
171
-
172
- reject(new Error("timeout reached"));
173
- }, timeout);
174
-
175
- requested = {
176
- ...requested,
177
- [header.nlmsg_seq]: {
178
- msgs: [],
179
- schedule,
180
- resolve,
181
- },
182
- };
183
-
184
- send({
185
- header,
186
- payload: message.payload,
187
- }).catch(reject);
188
- });
189
- })
190
- .then((packets) => {
191
- let errorCode = 0;
192
-
193
- const packetsWithoutError = packets.filter((pkt) => {
194
- if (pkt.header.nlmsg_type === NLMSG_ERROR) {
195
- const packetErrorCode = pkt.payload.readInt32LE(0);
196
- if (packetErrorCode !== 0) {
197
- errorCode = -packetErrorCode;
198
- }
199
- return false;
200
- } else {
201
- return true;
202
- }
203
- });
204
-
205
- return {
206
- errorCode,
207
- packets: packetsWithoutError,
208
- };
209
- });
210
- };
211
-
212
- const talk = (obj, options) => {
213
- return tryTalk(obj, options).then(({ errorCode, packets }) => {
214
- if (errorCode !== 0) {
215
- throw errorFactory.createFromErrorCode({ errorCode });
216
- }
217
-
218
- return packets;
219
- });
220
- };
221
-
222
- return sock
223
- .bind({
224
- sockaddr: netlinkAddress,
225
- })
226
- .then(() => {
227
- return sock.getsockname();
228
- })
229
- .then((actualAddressBuffer) => {
230
- const { nl_pid } = structures.sockaddr_nl.parse(actualAddressBuffer);
231
-
232
- return {
233
- nl_pid,
234
-
235
- talk,
236
- tryTalk,
237
- close,
238
- on: emitter.on.bind(emitter),
239
- };
240
- });
241
- });
242
- };
243
-
244
- export default {
245
- NLM_F_ECHO,
246
- NLM_F_REQUEST,
247
- NLM_F_MULTI,
248
- NLM_F_DUMP,
249
- NLM_F_ACK,
250
- NLM_F_CREATE,
251
- NLM_F_EXCL,
252
- NLM_F_MATCH,
253
-
254
- NLMSG_DONE,
255
- NLMSG_ERROR,
256
-
257
- open,
258
- createErrorFromErrorCode: errorFactory.createFromErrorCode,
259
- };
package/lib/parser.js DELETED
@@ -1,55 +0,0 @@
1
- import structures from "./structures.js";
2
-
3
- const align4 = (addr) => {
4
- return (addr + 3) & ~3;
5
- };
6
-
7
- const parseNetlinkMessage = ({ message }) => {
8
- const parsed = structures.nlmsghdr.parse(message);
9
-
10
- const header = {
11
- nlmsg_type: parsed.nlmsg_type,
12
- nlmsg_flags: parsed.nlmsg_flags,
13
- nlmsg_seq: parsed.nlmsg_seq,
14
- nlmsg_pid: parsed.nlmsg_pid
15
- };
16
-
17
- const payloadOffset = align4(structures.nlmsghdr.size);
18
- const payloadLength = parsed.nlmsg_len - BigInt(payloadOffset);
19
-
20
- if (payloadLength < 0) {
21
- throw new Error("negative payload length, packet malformed");
22
- }
23
-
24
- const payload = message.slice(payloadOffset, payloadOffset + Number(payloadLength));
25
- const space = align4(payloadOffset + payload.length);
26
-
27
- return {
28
- header,
29
- payload,
30
- space
31
- };
32
- };
33
-
34
- const parseMessage = ({ message }) => {
35
- let result = [];
36
-
37
- let remaining = message;
38
- while (remaining.length > 0) {
39
- const { header, payload, space } = parseNetlinkMessage({ message: remaining });
40
- const parsed = {
41
- header,
42
- payload
43
- };
44
-
45
- result = [...result, parsed ];
46
-
47
- remaining = remaining.slice(space);
48
- }
49
-
50
- return result;
51
- };
52
-
53
- export default {
54
- parseMessage
55
- };
package/lib/structures.js DELETED
@@ -1,21 +0,0 @@
1
- import struct from "ya-struct";
2
-
3
- const sockaddr_nl = struct.define(({ field }) => {
4
- field.UInt16("nl_family");
5
- field.UInt16("nl_pad");
6
- field.UInt32("nl_pid");
7
- field.UInt32("nl_groups");
8
- }).forHost();
9
-
10
- const nlmsghdr = struct.define(({ field }) => {
11
- field.UInt32("nlmsg_len");
12
- field.UInt16("nlmsg_type");
13
- field.UInt16("nlmsg_flags");
14
- field.UInt32("nlmsg_seq");
15
- field.UInt32("nlmsg_pid");
16
- }).forHost();
17
-
18
- export default {
19
- sockaddr_nl,
20
- nlmsghdr
21
- };
package/samples/test.js DELETED
@@ -1,11 +0,0 @@
1
- import netlink from "../lib/index.js";
2
-
3
- const NETLINK_ROUTE = 0;
4
-
5
- netlink.open({
6
- family: NETLINK_ROUTE
7
- }).then((nl) => {
8
- nl.close();
9
- }).catch((err) => {
10
- console.error(err);
11
- });
package/test/base.js DELETED
@@ -1,20 +0,0 @@
1
- /* global describe */
2
- /* global it */
3
-
4
- import netlink from "../lib/index.js";
5
-
6
- const NETLINK_ROUTE = 0;
7
-
8
- describe("opening", function () {
9
- this.timeout(5000);
10
-
11
- describe("normal case", () => {
12
- it("should open without error", () => {
13
- netlink.open({
14
- family: NETLINK_ROUTE
15
- }).then((nl) => {
16
- return nl.close();
17
- });
18
- });
19
- });
20
- });