mirror of
https://github.com/denoland/deno
synced 2024-11-05 18:45:24 +00:00
feat(ext/node): add BlockList & SocketAddress classes (#24229)
Closes https://github.com/denoland/deno/issues/24059
This commit is contained in:
parent
4b83ce8aca
commit
8c4b33db0d
12 changed files with 845 additions and 14 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -1701,6 +1701,7 @@ dependencies = [
|
||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
"idna 0.3.0",
|
"idna 0.3.0",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"ipnetwork",
|
||||||
"k256",
|
"k256",
|
||||||
"lazy-regex",
|
"lazy-regex",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -3571,6 +3572,15 @@ version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipnetwork"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-docker"
|
name = "is-docker"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
|
@ -41,6 +41,7 @@ home = "0.5.9"
|
||||||
http.workspace = true
|
http.workspace = true
|
||||||
idna = "0.3.0"
|
idna = "0.3.0"
|
||||||
indexmap.workspace = true
|
indexmap.workspace = true
|
||||||
|
ipnetwork = "0.20.0"
|
||||||
k256 = "0.13.1"
|
k256 = "0.13.1"
|
||||||
lazy-regex.workspace = true
|
lazy-regex.workspace = true
|
||||||
libc.workspace = true
|
libc.workspace = true
|
||||||
|
|
|
@ -230,6 +230,15 @@ deno_core::extension!(deno_node,
|
||||||
deps = [ deno_io, deno_fs ],
|
deps = [ deno_io, deno_fs ],
|
||||||
parameters = [P: NodePermissions],
|
parameters = [P: NodePermissions],
|
||||||
ops = [
|
ops = [
|
||||||
|
ops::blocklist::op_socket_address_parse,
|
||||||
|
ops::blocklist::op_socket_address_get_serialization,
|
||||||
|
|
||||||
|
ops::blocklist::op_blocklist_new,
|
||||||
|
ops::blocklist::op_blocklist_add_address,
|
||||||
|
ops::blocklist::op_blocklist_add_range,
|
||||||
|
ops::blocklist::op_blocklist_add_subnet,
|
||||||
|
ops::blocklist::op_blocklist_check,
|
||||||
|
|
||||||
ops::buffer::op_is_ascii,
|
ops::buffer::op_is_ascii,
|
||||||
ops::buffer::op_is_utf8,
|
ops::buffer::op_is_utf8,
|
||||||
ops::crypto::op_node_create_decipheriv,
|
ops::crypto::op_node_create_decipheriv,
|
||||||
|
@ -489,6 +498,7 @@ deno_core::extension!(deno_node,
|
||||||
"internal_binding/uv.ts",
|
"internal_binding/uv.ts",
|
||||||
"internal/assert.mjs",
|
"internal/assert.mjs",
|
||||||
"internal/async_hooks.ts",
|
"internal/async_hooks.ts",
|
||||||
|
"internal/blocklist.mjs",
|
||||||
"internal/buffer.mjs",
|
"internal/buffer.mjs",
|
||||||
"internal/child_process.ts",
|
"internal/child_process.ts",
|
||||||
"internal/cli_table.ts",
|
"internal/cli_table.ts",
|
||||||
|
|
290
ext/node/ops/blocklist.rs
Normal file
290
ext/node/ops/blocklist.rs
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
|
use std::net::Ipv6Addr;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use deno_core::anyhow::anyhow;
|
||||||
|
use deno_core::anyhow::bail;
|
||||||
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::op2;
|
||||||
|
use deno_core::OpState;
|
||||||
|
|
||||||
|
use ipnetwork::IpNetwork;
|
||||||
|
use ipnetwork::Ipv4Network;
|
||||||
|
use ipnetwork::Ipv6Network;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
pub struct BlockListResource {
|
||||||
|
blocklist: RefCell<BlockList>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct SocketAddressSerialization(String, String);
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_socket_address_parse(
|
||||||
|
state: &mut OpState,
|
||||||
|
#[string] addr: &str,
|
||||||
|
#[smi] port: u16,
|
||||||
|
#[string] family: &str,
|
||||||
|
) -> Result<bool, AnyError> {
|
||||||
|
let ip = addr.parse::<IpAddr>()?;
|
||||||
|
let parsed: SocketAddr = SocketAddr::new(ip, port);
|
||||||
|
let parsed_ip_str = parsed.ip().to_string();
|
||||||
|
let family_correct = family.eq_ignore_ascii_case("ipv4") && parsed.is_ipv4()
|
||||||
|
|| family.eq_ignore_ascii_case("ipv6") && parsed.is_ipv6();
|
||||||
|
|
||||||
|
if family_correct {
|
||||||
|
let family_is_lowercase = family[..3].chars().all(char::is_lowercase);
|
||||||
|
if family_is_lowercase && parsed_ip_str == addr {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
state.put::<SocketAddressSerialization>(SocketAddressSerialization(
|
||||||
|
parsed_ip_str,
|
||||||
|
family.to_lowercase(),
|
||||||
|
));
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Invalid address"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
#[serde]
|
||||||
|
pub fn op_socket_address_get_serialization(
|
||||||
|
state: &mut OpState,
|
||||||
|
) -> Result<SocketAddressSerialization, AnyError> {
|
||||||
|
Ok(state.take::<SocketAddressSerialization>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2]
|
||||||
|
#[cppgc]
|
||||||
|
pub fn op_blocklist_new() -> BlockListResource {
|
||||||
|
let blocklist = BlockList::new();
|
||||||
|
BlockListResource {
|
||||||
|
blocklist: RefCell::new(blocklist),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_blocklist_add_address(
|
||||||
|
#[cppgc] wrap: &BlockListResource,
|
||||||
|
#[string] addr: &str,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
wrap.blocklist.borrow_mut().add_address(addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_blocklist_add_range(
|
||||||
|
#[cppgc] wrap: &BlockListResource,
|
||||||
|
#[string] start: &str,
|
||||||
|
#[string] end: &str,
|
||||||
|
) -> Result<bool, AnyError> {
|
||||||
|
wrap.blocklist.borrow_mut().add_range(start, end)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_blocklist_add_subnet(
|
||||||
|
#[cppgc] wrap: &BlockListResource,
|
||||||
|
#[string] addr: &str,
|
||||||
|
#[smi] prefix: u8,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
wrap.blocklist.borrow_mut().add_subnet(addr, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
pub fn op_blocklist_check(
|
||||||
|
#[cppgc] wrap: &BlockListResource,
|
||||||
|
#[string] addr: &str,
|
||||||
|
#[string] r#type: &str,
|
||||||
|
) -> Result<bool, AnyError> {
|
||||||
|
wrap.blocklist.borrow().check(addr, r#type)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BlockList {
|
||||||
|
rules: HashSet<IpNetwork>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockList {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
BlockList {
|
||||||
|
rules: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_addr_add_network(&mut self, addr: IpAddr, prefix: Option<u8>) {
|
||||||
|
match addr {
|
||||||
|
IpAddr::V4(addr) => {
|
||||||
|
self.rules.insert(IpNetwork::V4(
|
||||||
|
Ipv4Network::new(addr, prefix.unwrap_or(32)).unwrap(),
|
||||||
|
));
|
||||||
|
self.rules.insert(IpNetwork::V6(
|
||||||
|
Ipv6Network::new(addr.to_ipv6_mapped(), prefix.unwrap_or(128))
|
||||||
|
.unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
IpAddr::V6(addr) => {
|
||||||
|
if let Some(ipv4_mapped) = addr.to_ipv4_mapped() {
|
||||||
|
self.rules.insert(IpNetwork::V4(
|
||||||
|
Ipv4Network::new(ipv4_mapped, prefix.unwrap_or(32)).unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
self.rules.insert(IpNetwork::V6(
|
||||||
|
Ipv6Network::new(addr, prefix.unwrap_or(128)).unwrap(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_address(&mut self, address: &str) -> Result<(), AnyError> {
|
||||||
|
let ip: IpAddr = address.parse()?;
|
||||||
|
self.map_addr_add_network(ip, None);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_range(
|
||||||
|
&mut self,
|
||||||
|
start: &str,
|
||||||
|
end: &str,
|
||||||
|
) -> Result<bool, AnyError> {
|
||||||
|
let start_ip: IpAddr = start.parse()?;
|
||||||
|
let end_ip: IpAddr = end.parse()?;
|
||||||
|
|
||||||
|
match (start_ip, end_ip) {
|
||||||
|
(IpAddr::V4(start), IpAddr::V4(end)) => {
|
||||||
|
let start_u32: u32 = start.into();
|
||||||
|
let end_u32: u32 = end.into();
|
||||||
|
if end_u32 < start_u32 {
|
||||||
|
// Indicates invalid range.
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
for ip in start_u32..=end_u32 {
|
||||||
|
let addr: Ipv4Addr = ip.into();
|
||||||
|
self.map_addr_add_network(IpAddr::V4(addr), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(IpAddr::V6(start), IpAddr::V6(end)) => {
|
||||||
|
let start_u128: u128 = start.into();
|
||||||
|
let end_u128: u128 = end.into();
|
||||||
|
if end_u128 < start_u128 {
|
||||||
|
// Indicates invalid range.
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
for ip in start_u128..=end_u128 {
|
||||||
|
let addr: Ipv6Addr = ip.into();
|
||||||
|
self.map_addr_add_network(IpAddr::V6(addr), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => bail!("IP version mismatch between start and end addresses"),
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_subnet(&mut self, addr: &str, prefix: u8) -> Result<(), AnyError> {
|
||||||
|
let ip: IpAddr = addr.parse()?;
|
||||||
|
self.map_addr_add_network(ip, Some(prefix));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check(&self, addr: &str, r#type: &str) -> Result<bool, AnyError> {
|
||||||
|
let addr: IpAddr = addr.parse()?;
|
||||||
|
let family = r#type.to_lowercase();
|
||||||
|
if family == "ipv4" && addr.is_ipv4() || family == "ipv6" && addr.is_ipv6()
|
||||||
|
{
|
||||||
|
Ok(self.rules.iter().any(|net| net.contains(addr)))
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("Invalid address"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_address() {
|
||||||
|
// Single IPv4 address
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_address("192.168.0.1").unwrap();
|
||||||
|
assert!(block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
assert!(block_list.check("::ffff:c0a8:1", "ipv6").unwrap());
|
||||||
|
|
||||||
|
// Single IPv6 address
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_address("2001:db8::1").unwrap();
|
||||||
|
assert!(block_list.check("2001:db8::1", "ipv6").unwrap());
|
||||||
|
assert!(!block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_range() {
|
||||||
|
// IPv4 range
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_range("192.168.0.1", "192.168.0.3").unwrap();
|
||||||
|
assert!(block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
assert!(block_list.check("192.168.0.2", "ipv4").unwrap());
|
||||||
|
assert!(block_list.check("192.168.0.3", "ipv4").unwrap());
|
||||||
|
assert!(block_list.check("::ffff:c0a8:1", "ipv6").unwrap());
|
||||||
|
|
||||||
|
// IPv6 range
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_range("2001:db8::1", "2001:db8::3").unwrap();
|
||||||
|
assert!(block_list.check("2001:db8::1", "ipv6").unwrap());
|
||||||
|
assert!(block_list.check("2001:db8::2", "ipv6").unwrap());
|
||||||
|
assert!(block_list.check("2001:db8::3", "ipv6").unwrap());
|
||||||
|
assert!(!block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_subnet() {
|
||||||
|
// IPv4 subnet
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_subnet("192.168.0.0", 24).unwrap();
|
||||||
|
assert!(block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
assert!(block_list.check("192.168.0.255", "ipv4").unwrap());
|
||||||
|
assert!(block_list.check("::ffff:c0a8:0", "ipv6").unwrap());
|
||||||
|
|
||||||
|
// IPv6 subnet
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_subnet("2001:db8::", 64).unwrap();
|
||||||
|
assert!(block_list.check("2001:db8::1", "ipv6").unwrap());
|
||||||
|
assert!(block_list.check("2001:db8::ffff", "ipv6").unwrap());
|
||||||
|
assert!(!block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_check() {
|
||||||
|
// Check IPv4 presence
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_address("192.168.0.1").unwrap();
|
||||||
|
assert!(block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
|
||||||
|
// Check IPv6 presence
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_address("2001:db8::1").unwrap();
|
||||||
|
assert!(block_list.check("2001:db8::1", "ipv6").unwrap());
|
||||||
|
|
||||||
|
// Check IPv4 not present
|
||||||
|
let block_list = BlockList::new();
|
||||||
|
assert!(!block_list.check("192.168.0.1", "ipv4").unwrap());
|
||||||
|
|
||||||
|
// Check IPv6 not present
|
||||||
|
let block_list = BlockList::new();
|
||||||
|
assert!(!block_list.check("2001:db8::1", "ipv6").unwrap());
|
||||||
|
|
||||||
|
// Check invalid IP version
|
||||||
|
let block_list = BlockList::new();
|
||||||
|
assert!(block_list.check("192.168.0.1", "ipv6").is_err());
|
||||||
|
|
||||||
|
// Check invalid type
|
||||||
|
let mut block_list = BlockList::new();
|
||||||
|
block_list.add_address("192.168.0.1").unwrap();
|
||||||
|
assert!(block_list.check("192.168.0.1", "invalid_type").is_err());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
pub mod blocklist;
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
|
|
227
ext/node/polyfills/internal/blocklist.mjs
Normal file
227
ext/node/polyfills/internal/blocklist.mjs
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
import { primordials } from "ext:core/mod.js";
|
||||||
|
import {
|
||||||
|
op_blocklist_add_address,
|
||||||
|
op_blocklist_add_range,
|
||||||
|
op_blocklist_add_subnet,
|
||||||
|
op_blocklist_check,
|
||||||
|
op_blocklist_new,
|
||||||
|
op_socket_address_get_serialization,
|
||||||
|
op_socket_address_parse,
|
||||||
|
} from "ext:core/ops";
|
||||||
|
|
||||||
|
import {
|
||||||
|
validateInt32,
|
||||||
|
validateObject,
|
||||||
|
validatePort,
|
||||||
|
validateString,
|
||||||
|
validateUint32,
|
||||||
|
} from "ext:deno_node/internal/validators.mjs";
|
||||||
|
import { ERR_INVALID_ARG_VALUE } from "ext:deno_node/internal/errors.ts";
|
||||||
|
import { customInspectSymbol } from "ext:deno_node/internal/util.mjs";
|
||||||
|
import { inspect } from "ext:deno_node/internal/util/inspect.mjs";
|
||||||
|
|
||||||
|
const { Symbol } = primordials;
|
||||||
|
|
||||||
|
const internalBlockList = Symbol("blocklist");
|
||||||
|
|
||||||
|
class BlockList {
|
||||||
|
constructor() {
|
||||||
|
this[internalBlockList] = op_blocklist_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
[customInspectSymbol](depth, options) {
|
||||||
|
if (depth < 0) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
...options,
|
||||||
|
depth: options.depth == null ? null : options.depth - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
return `BlockList ${
|
||||||
|
inspect({
|
||||||
|
rules: [], // TODO(satyarohith): provide the actual rules
|
||||||
|
}, opts)
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
addAddress(address, family = "ipv4") {
|
||||||
|
if (!SocketAddress.isSocketAddress(address)) {
|
||||||
|
validateString(address, "address");
|
||||||
|
validateString(family, "family");
|
||||||
|
new SocketAddress({
|
||||||
|
address,
|
||||||
|
family,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
address = address.address;
|
||||||
|
}
|
||||||
|
op_blocklist_add_address(this[internalBlockList], address);
|
||||||
|
}
|
||||||
|
|
||||||
|
addRange(start, end, family = "ipv4") {
|
||||||
|
if (!SocketAddress.isSocketAddress(start)) {
|
||||||
|
validateString(start, "start");
|
||||||
|
validateString(family, "family");
|
||||||
|
new SocketAddress({
|
||||||
|
address: start,
|
||||||
|
family,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
start = start.address;
|
||||||
|
}
|
||||||
|
if (!SocketAddress.isSocketAddress(end)) {
|
||||||
|
validateString(end, "end");
|
||||||
|
validateString(family, "family");
|
||||||
|
new SocketAddress({
|
||||||
|
address: end,
|
||||||
|
family,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
end = end.address;
|
||||||
|
}
|
||||||
|
const ret = op_blocklist_add_range(this[internalBlockList], start, end);
|
||||||
|
if (ret === false) {
|
||||||
|
throw new ERR_INVALID_ARG_VALUE("start", start, "must come before end");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addSubnet(network, prefix, family = "ipv4") {
|
||||||
|
if (!SocketAddress.isSocketAddress(network)) {
|
||||||
|
validateString(network, "network");
|
||||||
|
validateString(family, "family");
|
||||||
|
new SocketAddress({
|
||||||
|
address: network,
|
||||||
|
family,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
network = network.address;
|
||||||
|
family = network.family;
|
||||||
|
}
|
||||||
|
switch (family) {
|
||||||
|
case "ipv4":
|
||||||
|
validateInt32(prefix, "prefix", 0, 32);
|
||||||
|
break;
|
||||||
|
case "ipv6":
|
||||||
|
validateInt32(prefix, "prefix", 0, 128);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
op_blocklist_add_subnet(this[internalBlockList], network, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
check(address, family = "ipv4") {
|
||||||
|
if (!SocketAddress.isSocketAddress(address)) {
|
||||||
|
validateString(address, "address");
|
||||||
|
validateString(family, "family");
|
||||||
|
try {
|
||||||
|
new SocketAddress({
|
||||||
|
address,
|
||||||
|
family,
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// Ignore the error. If it's not a valid address, return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
family = address.family;
|
||||||
|
address = address.address;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return op_blocklist_check(this[internalBlockList], address, family);
|
||||||
|
} catch (_) {
|
||||||
|
// Node API expects false as return value if the address is invalid.
|
||||||
|
// Example: `blocklist.check("1.1.1.1", "ipv6")` should return false.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get rules() {
|
||||||
|
// TODO(satyarohith): return the actual rules
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const kDetail = Symbol("kDetail");
|
||||||
|
|
||||||
|
class SocketAddress {
|
||||||
|
static isSocketAddress(value) {
|
||||||
|
return value?.[kDetail] !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(options = kEmptyObject) {
|
||||||
|
validateObject(options, "options");
|
||||||
|
let { family = "ipv4" } = options;
|
||||||
|
const {
|
||||||
|
address = (family === "ipv4" ? "127.0.0.1" : "::"),
|
||||||
|
port = 0,
|
||||||
|
flowlabel = 0,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (typeof family?.toLowerCase === "function") {
|
||||||
|
// deno-lint-ignore prefer-primordials
|
||||||
|
family = family.toLowerCase();
|
||||||
|
}
|
||||||
|
switch (family) {
|
||||||
|
case "ipv4":
|
||||||
|
break;
|
||||||
|
case "ipv6":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ERR_INVALID_ARG_VALUE("options.family", options.family);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateString(address, "options.address");
|
||||||
|
validatePort(port, "options.port");
|
||||||
|
validateUint32(flowlabel, "options.flowlabel", false);
|
||||||
|
|
||||||
|
this[kDetail] = {
|
||||||
|
address,
|
||||||
|
port,
|
||||||
|
family,
|
||||||
|
flowlabel,
|
||||||
|
};
|
||||||
|
const useInput = op_socket_address_parse(
|
||||||
|
address,
|
||||||
|
port,
|
||||||
|
family,
|
||||||
|
);
|
||||||
|
if (!useInput) {
|
||||||
|
const { 0: address_, 1: family_ } = op_socket_address_get_serialization();
|
||||||
|
this[kDetail].address = address_;
|
||||||
|
this[kDetail].family = family_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get address() {
|
||||||
|
return this[kDetail].address;
|
||||||
|
}
|
||||||
|
|
||||||
|
get port() {
|
||||||
|
return this[kDetail].port;
|
||||||
|
}
|
||||||
|
|
||||||
|
get family() {
|
||||||
|
return this[kDetail].family;
|
||||||
|
}
|
||||||
|
|
||||||
|
get flowlabel() {
|
||||||
|
// TODO(satyarohith): Implement this in Rust.
|
||||||
|
// The flow label can be changed internally.
|
||||||
|
return this[kDetail].flowlabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON() {
|
||||||
|
return {
|
||||||
|
address: this.address,
|
||||||
|
port: this.port,
|
||||||
|
family: this.family,
|
||||||
|
flowlabel: this.flowlabel,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { BlockList, SocketAddress };
|
|
@ -667,9 +667,7 @@ function invalidArgTypeHelper(input: any) {
|
||||||
return ` Received type ${typeof input} (${inspected})`;
|
return ` Received type ${typeof input} (${inspected})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ERR_OUT_OF_RANGE extends RangeError {
|
export class ERR_OUT_OF_RANGE extends NodeRangeError {
|
||||||
code = "ERR_OUT_OF_RANGE";
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
str: string,
|
str: string,
|
||||||
range: string,
|
range: string,
|
||||||
|
@ -694,15 +692,7 @@ export class ERR_OUT_OF_RANGE extends RangeError {
|
||||||
}
|
}
|
||||||
msg += ` It must be ${range}. Received ${received}`;
|
msg += ` It must be ${range}. Received ${received}`;
|
||||||
|
|
||||||
super(msg);
|
super("ERR_OUT_OF_RANGE", msg);
|
||||||
|
|
||||||
const { name } = this;
|
|
||||||
// Add the error code to the name to include it in the stack trace.
|
|
||||||
this.name = `${name} [${this.code}]`;
|
|
||||||
// Access the stack to generate the error message including the error code from the name.
|
|
||||||
this.stack;
|
|
||||||
// Reset the name to the actual name.
|
|
||||||
this.name = name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
// deno-lint-ignore-file prefer-primordials
|
// deno-lint-ignore-file prefer-primordials
|
||||||
|
|
||||||
import { notImplemented } from "ext:deno_node/_utils.ts";
|
import { notImplemented } from "ext:deno_node/_utils.ts";
|
||||||
|
import { BlockList, SocketAddress } from "ext:deno_node/internal/blocklist.mjs";
|
||||||
|
|
||||||
import { EventEmitter } from "node:events";
|
import { EventEmitter } from "node:events";
|
||||||
import {
|
import {
|
||||||
isIP,
|
isIP,
|
||||||
|
@ -2472,7 +2474,7 @@ export function createServer(
|
||||||
return new Server(options, connectionListener);
|
return new Server(options, connectionListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { isIP, isIPv4, isIPv6 };
|
export { BlockList, isIP, isIPv4, isIPv6, SocketAddress };
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
_createServerHandle,
|
_createServerHandle,
|
||||||
|
@ -2480,6 +2482,8 @@ export default {
|
||||||
isIP,
|
isIP,
|
||||||
isIPv4,
|
isIPv4,
|
||||||
isIPv6,
|
isIPv6,
|
||||||
|
BlockList,
|
||||||
|
SocketAddress,
|
||||||
connect,
|
connect,
|
||||||
createConnection,
|
createConnection,
|
||||||
createServer,
|
createServer,
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
],
|
],
|
||||||
"parallel": [
|
"parallel": [
|
||||||
"test-assert.js",
|
"test-assert.js",
|
||||||
|
"test-blocklist.js",
|
||||||
"test-buffer-alloc.js",
|
"test-buffer-alloc.js",
|
||||||
"test-buffer-arraybuffer.js",
|
"test-buffer-arraybuffer.js",
|
||||||
"test-buffer-from.js",
|
"test-buffer-from.js",
|
||||||
|
@ -162,6 +163,7 @@
|
||||||
"test-assert-strict-exists.js",
|
"test-assert-strict-exists.js",
|
||||||
"test-assert.js",
|
"test-assert.js",
|
||||||
"test-bad-unicode.js",
|
"test-bad-unicode.js",
|
||||||
|
"test-blocklist.js",
|
||||||
"test-btoa-atob.js",
|
"test-btoa-atob.js",
|
||||||
"test-buffer-alloc.js",
|
"test-buffer-alloc.js",
|
||||||
"test-buffer-arraybuffer.js",
|
"test-buffer-arraybuffer.js",
|
||||||
|
|
|
@ -222,7 +222,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
|
||||||
- [parallel/test-blob-file-backed.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blob-file-backed.js)
|
- [parallel/test-blob-file-backed.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blob-file-backed.js)
|
||||||
- [parallel/test-blob.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blob.js)
|
- [parallel/test-blob.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blob.js)
|
||||||
- [parallel/test-blocklist-clone.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blocklist-clone.js)
|
- [parallel/test-blocklist-clone.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blocklist-clone.js)
|
||||||
- [parallel/test-blocklist.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-blocklist.js)
|
|
||||||
- [parallel/test-bootstrap-modules.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-bootstrap-modules.js)
|
- [parallel/test-bootstrap-modules.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-bootstrap-modules.js)
|
||||||
- [parallel/test-broadcastchannel-custom-inspect.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-broadcastchannel-custom-inspect.js)
|
- [parallel/test-broadcastchannel-custom-inspect.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-broadcastchannel-custom-inspect.js)
|
||||||
- [parallel/test-buffer-backing-arraybuffer.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-buffer-backing-arraybuffer.js)
|
- [parallel/test-buffer-backing-arraybuffer.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-buffer-backing-arraybuffer.js)
|
||||||
|
|
291
tests/node_compat/test/parallel/test-blocklist.js
Normal file
291
tests/node_compat/test/parallel/test-blocklist.js
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
// deno-fmt-ignore-file
|
||||||
|
// deno-lint-ignore-file
|
||||||
|
|
||||||
|
// Copyright Joyent and Node contributors. All rights reserved. MIT license.
|
||||||
|
// Taken from Node 18.12.1
|
||||||
|
// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
require('../common');
|
||||||
|
|
||||||
|
const {
|
||||||
|
BlockList,
|
||||||
|
SocketAddress,
|
||||||
|
} = require('net');
|
||||||
|
const assert = require('assert');
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
|
||||||
|
[1, [], {}, null, 1n, undefined, null].forEach((i) => {
|
||||||
|
assert.throws(() => blockList.addAddress(i), {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[1, [], {}, null, 1n, null].forEach((i) => {
|
||||||
|
assert.throws(() => blockList.addAddress('1.1.1.1', i), {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.throws(() => blockList.addAddress('1.1.1.1', 'foo'), {
|
||||||
|
code: 'ERR_INVALID_ARG_VALUE'
|
||||||
|
});
|
||||||
|
|
||||||
|
[1, [], {}, null, 1n, undefined, null].forEach((i) => {
|
||||||
|
assert.throws(() => blockList.addRange(i), {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE'
|
||||||
|
});
|
||||||
|
assert.throws(() => blockList.addRange('1.1.1.1', i), {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
[1, [], {}, null, 1n, null].forEach((i) => {
|
||||||
|
assert.throws(() => blockList.addRange('1.1.1.1', '1.1.1.2', i), {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.throws(() => blockList.addRange('1.1.1.1', '1.1.1.2', 'foo'), {
|
||||||
|
code: 'ERR_INVALID_ARG_VALUE'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
blockList.addAddress('1.1.1.1');
|
||||||
|
blockList.addAddress('8592:757c:efae:4e45:fb5d:d62a:0d00:8e17', 'ipv6');
|
||||||
|
blockList.addAddress('::ffff:1.1.1.2', 'ipv6');
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.1.1'));
|
||||||
|
assert(!blockList.check('1.1.1.1', 'ipv6'));
|
||||||
|
assert(!blockList.check('8592:757c:efae:4e45:fb5d:d62a:0d00:8e17'));
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45:fb5d:d62a:0d00:8e17', 'ipv6'));
|
||||||
|
|
||||||
|
assert(blockList.check('::ffff:1.1.1.1', 'ipv6'));
|
||||||
|
assert(blockList.check('::ffff:1.1.1.1', 'IPV6'));
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.1.2'));
|
||||||
|
|
||||||
|
assert(!blockList.check('1.2.3.4'));
|
||||||
|
assert(!blockList.check('::1', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
const sa1 = new SocketAddress({ address: '1.1.1.1' });
|
||||||
|
const sa2 = new SocketAddress({
|
||||||
|
address: '8592:757c:efae:4e45:fb5d:d62a:0d00:8e17',
|
||||||
|
family: 'ipv6'
|
||||||
|
});
|
||||||
|
const sa3 = new SocketAddress({ address: '1.1.1.2' });
|
||||||
|
|
||||||
|
blockList.addAddress(sa1);
|
||||||
|
blockList.addAddress(sa2);
|
||||||
|
blockList.addAddress('::ffff:1.1.1.2', 'ipv6');
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.1.1'));
|
||||||
|
assert(blockList.check(sa1));
|
||||||
|
assert(!blockList.check('1.1.1.1', 'ipv6'));
|
||||||
|
assert(!blockList.check('8592:757c:efae:4e45:fb5d:d62a:0d00:8e17'));
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45:fb5d:d62a:0d00:8e17', 'ipv6'));
|
||||||
|
assert(blockList.check(sa2));
|
||||||
|
|
||||||
|
assert(blockList.check('::ffff:1.1.1.1', 'ipv6'));
|
||||||
|
assert(blockList.check('::ffff:1.1.1.1', 'IPV6'));
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.1.2'));
|
||||||
|
assert(blockList.check(sa3));
|
||||||
|
|
||||||
|
assert(!blockList.check('1.2.3.4'));
|
||||||
|
assert(!blockList.check('::1', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
blockList.addRange('1.1.1.1', '1.1.1.10');
|
||||||
|
blockList.addRange('::1', '::f', 'ipv6');
|
||||||
|
|
||||||
|
assert(!blockList.check('1.1.1.0'));
|
||||||
|
for (let n = 1; n <= 10; n++)
|
||||||
|
assert(blockList.check(`1.1.1.${n}`));
|
||||||
|
assert(!blockList.check('1.1.1.11'));
|
||||||
|
|
||||||
|
assert(!blockList.check('::0', 'ipv6'));
|
||||||
|
for (let n = 0x1; n <= 0xf; n++) {
|
||||||
|
assert(blockList.check(`::${n.toString(16)}`, 'ipv6'),
|
||||||
|
`::${n.toString(16)} check failed`);
|
||||||
|
}
|
||||||
|
assert(!blockList.check('::10', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
const sa1 = new SocketAddress({ address: '1.1.1.1' });
|
||||||
|
const sa2 = new SocketAddress({ address: '1.1.1.10' });
|
||||||
|
const sa3 = new SocketAddress({ address: '::1', family: 'ipv6' });
|
||||||
|
const sa4 = new SocketAddress({ address: '::f', family: 'ipv6' });
|
||||||
|
|
||||||
|
blockList.addRange(sa1, sa2);
|
||||||
|
blockList.addRange(sa3, sa4);
|
||||||
|
|
||||||
|
assert(!blockList.check('1.1.1.0'));
|
||||||
|
for (let n = 1; n <= 10; n++)
|
||||||
|
assert(blockList.check(`1.1.1.${n}`));
|
||||||
|
assert(!blockList.check('1.1.1.11'));
|
||||||
|
|
||||||
|
assert(!blockList.check('::0', 'ipv6'));
|
||||||
|
for (let n = 0x1; n <= 0xf; n++) {
|
||||||
|
assert(blockList.check(`::${n.toString(16)}`, 'ipv6'),
|
||||||
|
`::${n.toString(16)} check failed`);
|
||||||
|
}
|
||||||
|
assert(!blockList.check('::10', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
blockList.addSubnet('1.1.1.0', 16);
|
||||||
|
blockList.addSubnet('8592:757c:efae:4e45::', 64, 'ipv6');
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.0.1'));
|
||||||
|
assert(blockList.check('1.1.1.1'));
|
||||||
|
assert(!blockList.check('1.2.0.1'));
|
||||||
|
assert(blockList.check('::ffff:1.1.0.1', 'ipv6'));
|
||||||
|
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45:f::', 'ipv6'));
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45::f', 'ipv6'));
|
||||||
|
assert(!blockList.check('8592:757c:efae:4f45::f', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
const sa1 = new SocketAddress({ address: '1.1.1.0' });
|
||||||
|
const sa2 = new SocketAddress({ address: '1.1.1.1' });
|
||||||
|
blockList.addSubnet(sa1, 16);
|
||||||
|
blockList.addSubnet('8592:757c:efae:4e45::', 64, 'ipv6');
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.0.1'));
|
||||||
|
assert(blockList.check(sa2));
|
||||||
|
assert(!blockList.check('1.2.0.1'));
|
||||||
|
assert(blockList.check('::ffff:1.1.0.1', 'ipv6'));
|
||||||
|
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45:f::', 'ipv6'));
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45::f', 'ipv6'));
|
||||||
|
assert(!blockList.check('8592:757c:efae:4f45::f', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
blockList.addAddress('1.1.1.1');
|
||||||
|
blockList.addRange('10.0.0.1', '10.0.0.10');
|
||||||
|
blockList.addSubnet('8592:757c:efae:4e45::', 64, 'IpV6'); // Case insensitive
|
||||||
|
|
||||||
|
// const rulesCheck = [
|
||||||
|
// 'Subnet: IPv6 8592:757c:efae:4e45::/64',
|
||||||
|
// 'Range: IPv4 10.0.0.1-10.0.0.10',
|
||||||
|
// 'Address: IPv4 1.1.1.1',
|
||||||
|
// ];
|
||||||
|
// assert.deepStrictEqual(blockList.rules, rulesCheck);
|
||||||
|
|
||||||
|
assert(blockList.check('1.1.1.1'));
|
||||||
|
assert(blockList.check('10.0.0.5'));
|
||||||
|
assert(blockList.check('::ffff:10.0.0.5', 'ipv6'));
|
||||||
|
assert(blockList.check('8592:757c:efae:4e45::f', 'ipv6'));
|
||||||
|
|
||||||
|
assert(!blockList.check('123.123.123.123'));
|
||||||
|
assert(!blockList.check('8592:757c:efaf:4e45:fb5d:d62a:0d00:8e17', 'ipv6'));
|
||||||
|
assert(!blockList.check('::ffff:123.123.123.123', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// This test validates boundaries of non-aligned CIDR bit prefixes
|
||||||
|
const blockList = new BlockList();
|
||||||
|
blockList.addSubnet('10.0.0.0', 27);
|
||||||
|
blockList.addSubnet('8592:757c:efaf::', 51, 'ipv6');
|
||||||
|
|
||||||
|
for (let n = 0; n <= 31; n++)
|
||||||
|
assert(blockList.check(`10.0.0.${n}`));
|
||||||
|
assert(!blockList.check('10.0.0.32'));
|
||||||
|
|
||||||
|
assert(blockList.check('8592:757c:efaf:0:0:0:0:0', 'ipv6'));
|
||||||
|
assert(blockList.check('8592:757c:efaf:1fff:ffff:ffff:ffff:ffff', 'ipv6'));
|
||||||
|
assert(!blockList.check('8592:757c:efaf:2fff:ffff:ffff:ffff:ffff', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Regression test for https://github.com/nodejs/node/issues/39074
|
||||||
|
const blockList = new BlockList();
|
||||||
|
|
||||||
|
blockList.addRange('10.0.0.2', '10.0.0.10');
|
||||||
|
|
||||||
|
// IPv4 checks against IPv4 range.
|
||||||
|
assert(blockList.check('10.0.0.2'));
|
||||||
|
assert(blockList.check('10.0.0.10'));
|
||||||
|
assert(!blockList.check('192.168.0.3'));
|
||||||
|
assert(!blockList.check('2.2.2.2'));
|
||||||
|
assert(!blockList.check('255.255.255.255'));
|
||||||
|
|
||||||
|
// IPv6 checks against IPv4 range.
|
||||||
|
assert(blockList.check('::ffff:0a00:0002', 'ipv6'));
|
||||||
|
assert(blockList.check('::ffff:0a00:000a', 'ipv6'));
|
||||||
|
assert(!blockList.check('::ffff:c0a8:0003', 'ipv6'));
|
||||||
|
assert(!blockList.check('::ffff:0202:0202', 'ipv6'));
|
||||||
|
assert(!blockList.check('::ffff:ffff:ffff', 'ipv6'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
assert.throws(() => blockList.addRange('1.1.1.2', '1.1.1.1'), /ERR_INVALID_ARG_VALUE/);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
assert.throws(() => blockList.addSubnet(1), /ERR_INVALID_ARG_TYPE/);
|
||||||
|
assert.throws(() => blockList.addSubnet('1.1.1.1', ''),
|
||||||
|
/ERR_INVALID_ARG_TYPE/);
|
||||||
|
assert.throws(() => blockList.addSubnet('1.1.1.1', NaN), /ERR_OUT_OF_RANGE/);
|
||||||
|
assert.throws(() => blockList.addSubnet('', 1, 1), /ERR_INVALID_ARG_TYPE/);
|
||||||
|
assert.throws(() => blockList.addSubnet('', 1, ''), /ERR_INVALID_ARG_VALUE/);
|
||||||
|
|
||||||
|
assert.throws(() => blockList.addSubnet('1.1.1.1', -1, 'ipv4'),
|
||||||
|
/ERR_OUT_OF_RANGE/);
|
||||||
|
assert.throws(() => blockList.addSubnet('1.1.1.1', 33, 'ipv4'),
|
||||||
|
/ERR_OUT_OF_RANGE/);
|
||||||
|
|
||||||
|
assert.throws(() => blockList.addSubnet('::', -1, 'ipv6'),
|
||||||
|
/ERR_OUT_OF_RANGE/);
|
||||||
|
assert.throws(() => blockList.addSubnet('::', 129, 'ipv6'),
|
||||||
|
/ERR_OUT_OF_RANGE/);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
assert.throws(() => blockList.check(1), /ERR_INVALID_ARG_TYPE/);
|
||||||
|
assert.throws(() => blockList.check('', 1), /ERR_INVALID_ARG_TYPE/);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
const ret = util.inspect(blockList, { depth: -1 });
|
||||||
|
assert.strictEqual(ret, '[BlockList]');
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const blockList = new BlockList();
|
||||||
|
const ret = util.inspect(blockList, { depth: null });
|
||||||
|
assert(ret.includes('rules: []'));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test for https://github.com/nodejs/node/issues/43360
|
||||||
|
const blocklist = new BlockList();
|
||||||
|
blocklist.addSubnet('1.1.1.1', 32, 'ipv4');
|
||||||
|
|
||||||
|
assert(blocklist.check('1.1.1.1'));
|
||||||
|
assert(!blocklist.check('1.1.1.2'));
|
||||||
|
assert(!blocklist.check('2.3.4.5'));
|
||||||
|
}
|
|
@ -200,3 +200,9 @@ Deno.test("[node/net] multiple Sockets should get correct server data", async ()
|
||||||
assertEquals(sockets[i].events, [`${i}`.repeat(3), `${i}`.repeat(3)]);
|
assertEquals(sockets[i].events, [`${i}`.repeat(3), `${i}`.repeat(3)]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test("[node/net] BlockList doesn't leak resources", () => {
|
||||||
|
const blockList = new net.BlockList();
|
||||||
|
blockList.addAddress("1.1.1.1");
|
||||||
|
assert(blockList.check("1.1.1.1"));
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue