Skip to content

Commit b5a2d3e

Browse files
authored
feat: add isGlobalUnicast function (#2872)
Adds functions for detected global unicast IPv6 multiaddrs and IP addresses.
1 parent 06f79b6 commit b5a2d3e

File tree

6 files changed

+152
-1
lines changed

6 files changed

+152
-1
lines changed

packages/utils/package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@
7676
"types": "./dist/src/filters/index.d.ts",
7777
"import": "./dist/src/filters/index.js"
7878
},
79+
"./global-unicast-ip": {
80+
"types": "./dist/src/global-unicast-ip.d.ts",
81+
"import": "./dist/src/global-unicast-ip.js"
82+
},
7983
"./ip-port-to-multiaddr": {
8084
"types": "./dist/src/ip-port-to-multiaddr.d.ts",
8185
"import": "./dist/src/ip-port-to-multiaddr.js"
@@ -92,6 +96,10 @@
9296
"types": "./dist/src/moving-average.d.ts",
9397
"import": "./dist/src/moving-average.js"
9498
},
99+
"./multiaddr/is-global-unicast": {
100+
"types": "./dist/src/multiaddr/is-global-unicast.d.ts",
101+
"import": "./dist/src/multiaddr/is-global-unicast.js"
102+
},
95103
"./multiaddr/is-link-local": {
96104
"types": "./dist/src/multiaddr/is-link-local.d.ts",
97105
"import": "./dist/src/multiaddr/is-link-local.js"
@@ -164,6 +172,7 @@
164172
},
165173
"dependencies": {
166174
"@chainsafe/is-ip": "^2.0.2",
175+
"@chainsafe/netmask": "^2.0.0",
167176
"@libp2p/crypto": "^5.0.7",
168177
"@libp2p/interface": "^2.2.1",
169178
"@libp2p/logger": "^5.1.4",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { isIPv6 } from '@chainsafe/is-ip'
2+
import { cidrContains } from '@chainsafe/netmask'
3+
4+
export function isGlobalUnicastIp (ip: string): boolean {
5+
if (isIPv6(ip)) {
6+
return cidrContains('2000::/3', ip)
7+
}
8+
9+
return false
10+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { cidrContains } from '@chainsafe/netmask'
2+
import type { Multiaddr } from '@multiformats/multiaddr'
3+
4+
const CODEC_IP6 = 0x29
5+
6+
/**
7+
* Check if a given multiaddr is an IPv6 global unicast address
8+
*/
9+
export function isGlobalUnicast (ma: Multiaddr): boolean {
10+
try {
11+
const [[codec, value]] = ma.stringTuples()
12+
13+
if (value == null) {
14+
return false
15+
}
16+
17+
if (codec === CODEC_IP6) {
18+
return cidrContains('2000::/3', value)
19+
}
20+
} catch {
21+
22+
}
23+
24+
return false
25+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/* eslint-env mocha */
2+
3+
import { expect } from 'aegir/chai'
4+
import { isGlobalUnicastIp } from '../src/global-unicast-ip.js'
5+
6+
describe('isGlobalUnicastIp', () => {
7+
it('identifies ip4 multiaddrs as non-global unicast', () => {
8+
[
9+
'169.254.35.4',
10+
'169.254.35.4',
11+
'169.254.0.0',
12+
'169.254.255.255',
13+
'101.0.26.90',
14+
'10.0.0.1',
15+
'192.168.0.1',
16+
'172.16.0.1'
17+
].forEach(ma => {
18+
expect(isGlobalUnicastIp(ma)).to.be.false(`"${ma}" was identified as global unicast`)
19+
})
20+
})
21+
22+
it('identifies global unicast ip6 multiaddrs', () => {
23+
[
24+
'2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095',
25+
'2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095%en0'
26+
].forEach(ma => {
27+
expect(isGlobalUnicastIp(ma)).to.be.true(`"${ma}" was not identified as global unicast`)
28+
})
29+
})
30+
31+
it('identifies non global unicast ip6 multiaddrs', () => {
32+
[
33+
'::',
34+
'fe80::1%lo0',
35+
'fe80::1%lo0',
36+
'fe80::1893:def4:af04:635a%en',
37+
'fe80::1893:def4:af04:635a',
38+
'fe80::1893:def4:af04:635a',
39+
'::2:0:59c:a24:801'
40+
].forEach(ma => {
41+
expect(isGlobalUnicastIp(ma)).to.be.false(`"${ma}" was identified as global unicast`)
42+
})
43+
})
44+
45+
it('identifies other multiaddrs as not global unicast addresses', () => {
46+
[
47+
'wss0.bootstrap.libp2p.io',
48+
'wss0.bootstrap.libp2p.io'
49+
].forEach(ma => {
50+
expect(isGlobalUnicastIp(ma)).to.be.false(`"${ma}" was identified as global unicast`)
51+
})
52+
})
53+
})

packages/utils/test/link-local-ip.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe('isLinkLocalIp', () => {
4040

4141
it('identifies non link-local ip6 multiaddrs', () => {
4242
[
43-
'2001:8a0:7ac5:4201:3ac9:86ff:fe31',
43+
'2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095',
4444
'::'
4545
].forEach(ma => {
4646
expect(isLinkLocalIp(ma)).to.be.false()
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* eslint-env mocha */
2+
3+
import { multiaddr } from '@multiformats/multiaddr'
4+
import { expect } from 'aegir/chai'
5+
import { isGlobalUnicast } from '../../src/multiaddr/is-global-unicast.js'
6+
7+
describe('multiaddr isGlobalUnicast', () => {
8+
it('identifies ip4 multiaddrs as non-global unicast', () => {
9+
[
10+
multiaddr('/ip4/169.254.35.4'),
11+
multiaddr('/ip4/169.254.35.4/tcp/1000'),
12+
multiaddr('/ip4/169.254.0.0/tcp/1000'),
13+
multiaddr('/ip4/169.254.255.255/tcp/1000'),
14+
multiaddr('/ip4/101.0.26.90/tcp/1000'),
15+
multiaddr('/ip4/10.0.0.1/tcp/1000'),
16+
multiaddr('/ip4/192.168.0.1/tcp/1000'),
17+
multiaddr('/ip4/172.16.0.1/tcp/1000')
18+
].forEach(ma => {
19+
expect(isGlobalUnicast(ma)).to.be.false(`"${ma}" was identified as global unicast`)
20+
})
21+
})
22+
23+
it('identifies global unicast ip6 multiaddrs', () => {
24+
[
25+
multiaddr('/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/1000'),
26+
multiaddr('/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095%en0/tcp/1000')
27+
].forEach(ma => {
28+
expect(isGlobalUnicast(ma)).to.be.true(`"${ma}" was not identified as global unicast`)
29+
})
30+
})
31+
32+
it('identifies non global unicast ip6 multiaddrs', () => {
33+
[
34+
multiaddr('/ip6/fe80::1%lo0'),
35+
multiaddr('/ip6/fe80::1%lo0/tcp/1000'),
36+
multiaddr('/ip6/fe80::1893:def4:af04:635a%en'),
37+
multiaddr('/ip6/fe80::1893:def4:af04:635a'),
38+
multiaddr('/ip6/fe80::1893:def4:af04:635a/udp/2183'),
39+
multiaddr('/ip6/::/tcp/1000'),
40+
multiaddr('/ip6/::2:0:59c:a24:801/tcp/64142')
41+
].forEach(ma => {
42+
expect(isGlobalUnicast(ma)).to.be.false(`"${ma}" was identified as global unicast`)
43+
})
44+
})
45+
46+
it('identifies other multiaddrs as not global unicast addresses', () => {
47+
[
48+
multiaddr('/dns4/wss0.bootstrap.libp2p.io/tcp/443'),
49+
multiaddr('/dns6/wss0.bootstrap.libp2p.io/tcp/443')
50+
].forEach(ma => {
51+
expect(isGlobalUnicast(ma)).to.be.false(`"${ma}" was identified as global unicast`)
52+
})
53+
})
54+
})

0 commit comments

Comments
 (0)