From acb82f3f5f9c413ec442c4dedff8ddcddc894de5 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Thu, 29 Feb 2024 12:27:21 +0800 Subject: [PATCH] fix: should return scopeid = 0 address on IPv6 --- .gitignore | 1 + package.json | 3 ++- src/address.ts | 38 +++++++++++++++++++++++++++++--------- test/address.test.ts | 31 +++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index b4b3d69..12ea89d 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ npm-debug.log test/fixtures/ts/*.js .tshy* dist/ +package-lock.json diff --git a/package.json b/package.json index 1db6a85..9eda0a9 100644 --- a/package.json +++ b/package.json @@ -75,5 +75,6 @@ } } }, - "types": "./dist/commonjs/index.d.ts" + "types": "./dist/commonjs/index.d.ts", + "main": "./dist/commonjs/index.js" } diff --git a/src/address.ts b/src/address.ts index 883a017..56c3037 100644 --- a/src/address.ts +++ b/src/address.ts @@ -58,6 +58,28 @@ function matchName(actualFamily: string | number, expectedFamily: string | numbe return actualFamily === expectedFamily; } +function findAddressFromInterface(items: os.NetworkInterfaceInfo[], expectedFamily: string | number, + ignoreLoAddress = false) { + let firstMatchItem; + for (const item of items) { + if (matchName(item.family, expectedFamily)) { + if (ignoreLoAddress && item.address.startsWith('127.')) { + continue; + } + if (expectedFamily === 'IPv6') { + // find the scopeid = 0 item + if (item.scopeid === 0) return item; + if (!firstMatchItem) { + firstMatchItem = item; + } + } else { + return item; + } + } + } + return firstMatchItem; +} + export function getInterfaceAddress(family?: string, name?: string) { const interfaces = os.networkInterfaces(); const noName = !name; @@ -68,10 +90,9 @@ export function getInterfaceAddress(family?: string, name?: string) { const interfaceName = name + (i >= 0 ? i : ''); // support 'lo' and 'lo0' const items = interfaces[interfaceName]; if (items) { - for (const item of items) { - if (matchName(item.family, family)) { - return item; - } + const item = findAddressFromInterface(items, family); + if (item) { + return item; } } } @@ -82,11 +103,10 @@ export function getInterfaceAddress(family?: string, name?: string) { for (const k in interfaces) { const items = interfaces[k]; if (items) { - for (const item of items) { - // all 127 addresses are local and should be ignored - if (matchName(item.family, family) && !item.address.startsWith('127.')) { - return item; - } + // all 127 addresses are local and should be ignored + const item = findAddressFromInterface(items, family, true); + if (item) { + return item; } } } diff --git a/test/address.test.ts b/test/address.test.ts index 9159e5b..cf520f8 100644 --- a/test/address.test.ts +++ b/test/address.test.ts @@ -232,6 +232,37 @@ describe('test/address.test.ts', () => { assert.equal(addressAll.ip('utun'), '10.206.52.79'); assert.equal(addressAll.ipv6('utun'), 'fe80::696:ad3d:eeec:1722'); }); + + it('should return scopeid = 0 address', () => { + mm(os, 'networkInterfaces', () => { + return { + lo: + [{ address: '127.0.0.1', + family: 'IPv4', + internal: true }], + utun0: + [ + { + address: 'fe80::696:ad3d:eeec:1722', + family: 'IPv6', + internal: false, + scopeid: 20, + }, + { + address: 'fe80::696:ad3d:eeee:ffff:1:1000:3380:b81a:2dd4:373e:1234', + family: 'IPv6', + internal: false, + scopeid: 0, + }, + ], + utun1: + [{ address: '10.206.52.79', + family: 'IPv4', + internal: false }] }; + }); + assert.equal(addressAll.ip('utun'), '10.206.52.79'); + assert.equal(addressAll.ipv6('utun'), 'fe80::696:ad3d:eeee:ffff:1:1000:3380:b81a:2dd4:373e:1234'); + }); }); describe('address.dns()', () => {