dgram: support blocklist in udp · nodejs/node@ba9d539
@@ -39,6 +39,7 @@ const {
3939ERR_BUFFER_OUT_OF_BOUNDS,
4040ERR_INVALID_ARG_TYPE,
4141ERR_INVALID_FD_TYPE,
42+ERR_IP_BLOCKED,
4243ERR_MISSING_ARGS,
4344ERR_SOCKET_ALREADY_BOUND,
4445ERR_SOCKET_BAD_BUFFER_SIZE,
@@ -53,6 +54,7 @@ const {
5354 _createSocketHandle,
5455 newHandle,
5556} = require('internal/dgram');
57+const { isIP } = require('internal/net');
5658const {
5759 isInt32,
5860 validateAbortSignal,
@@ -97,12 +99,18 @@ let _cluster = null;
9799function lazyLoadCluster() {
98100return _cluster ??= require('cluster');
99101}
102+let _blockList = null;
103+function lazyLoadBlockList() {
104+return _blockList ??= require('internal/blocklist').BlockList;
105+}
100106101107function Socket(type, listener) {
102108FunctionPrototypeCall(EventEmitter, this);
103109let lookup;
104110let recvBufferSize;
105111let sendBufferSize;
112+let receiveBlockList;
113+let sendBlockList;
106114107115let options;
108116if (type !== null && typeof type === 'object') {
@@ -117,6 +125,18 @@ function Socket(type, listener) {
117125}
118126recvBufferSize = options.recvBufferSize;
119127sendBufferSize = options.sendBufferSize;
128+if (options.receiveBlockList) {
129+if (!lazyLoadBlockList().isBlockList(options.receiveBlockList)) {
130+throw new ERR_INVALID_ARG_TYPE('options.receiveBlockList', 'net.BlockList', options.receiveBlockList);
131+}
132+receiveBlockList = options.receiveBlockList;
133+}
134+if (options.sendBlockList) {
135+if (!lazyLoadBlockList().isBlockList(options.sendBlockList)) {
136+throw new ERR_INVALID_ARG_TYPE('options.sendBlockList', 'net.BlockList', options.sendBlockList);
137+}
138+sendBlockList = options.sendBlockList;
139+}
120140}
121141122142const handle = newHandle(type, lookup);
@@ -139,6 +159,8 @@ function Socket(type, listener) {
139159ipv6Only: options?.ipv6Only,
140160 recvBufferSize,
141161 sendBufferSize,
162+ receiveBlockList,
163+ sendBlockList,
142164};
143165144166if (options?.signal !== undefined) {
@@ -437,7 +459,9 @@ function doConnect(ex, self, ip, address, port, callback) {
437459const state = self[kStateSymbol];
438460if (!state.handle)
439461return;
440-462+if (!ex && state.sendBlockList?.check(ip, `ipv${isIP(ip)}`)) {
463+ex = new ERR_IP_BLOCKED(ip);
464+}
441465if (!ex) {
442466const err = state.handle.connect(ip, port);
443467if (err) {
@@ -701,6 +725,13 @@ function doSend(ex, self, ip, list, address, port, callback) {
701725return;
702726}
703727728+if (ip && state.sendBlockList?.check(ip, `ipv${isIP(ip)}`)) {
729+if (callback) {
730+process.nextTick(callback, new ERR_IP_BLOCKED(ip));
731+}
732+return;
733+}
734+704735const req = new SendWrap();
705736req.list = list; // Keep reference alive.
706737req.address = address;
@@ -949,6 +980,10 @@ function onMessage(nread, handle, buf, rinfo) {
949980if (nread < 0) {
950981return self.emit('error', new ErrnoException(nread, 'recvmsg'));
951982}
983+if (self[kStateSymbol]?.receiveBlockList?.check(rinfo.address,
984+rinfo.family?.toLocaleLowerCase())) {
985+return;
986+}
952987rinfo.size = buf.length; // compatibility
953988self.emit('message', buf, rinfo);
954989}