Socket
Socket
Sign inDemoInstall

default-gateway

Package Overview
Dependencies
16
Maintainers
1
Versions
54
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 6.0.3 to 7.0.0

320

index.js

@@ -1,35 +0,301 @@

"use strict";
import {isIP} from "node:net";
import {execa, execaSync} from "execa";
import {platform, type, release, networkInterfaces} from "node:os";
const {platform, type} = require("os");
const plat = platform();
const dests = new Set(["default", "0.0.0.0", "0.0.0.0/0", "::", "::/0"]);
let promise, sync;
const supportedPlatforms = new Set([
"aix",
"android",
"darwin",
"freebsd",
"linux",
"openbsd",
"sunos",
"win32"
]);
if (plat === "linux") {
const args = {
v4: ["-4", "r"],
v6: ["-6", "r"],
};
const plat = platform();
const parse = (stdout, family) => {
for (const line of (stdout || "").trim().split("\n")) {
const results = /default( via .+?)?( dev .+?)( |$)/.exec(line) || [];
const gateway = (results[1] || "").substring(5);
const iface = (results[2] || "").substring(5);
if (gateway && isIP(gateway)) { // default via 1.2.3.4 dev en0
return {gateway, int: (iface ?? null)};
} else if (iface && !gateway) { // default via dev en0
const interfaces = networkInterfaces();
const addresses = interfaces[iface];
for (const addr of addresses || []) {
if (addr.family.substring(2) === family && isIP(addr.address)) {
return {gateway: addr.address, int: (iface ?? null)};
}
}
}
}
throw new Error("Unable to determine default gateway");
};
if (supportedPlatforms.has(plat)) {
let file = plat;
if (plat === "aix") {
file = type() === "OS400" ? "ibmi" : "sunos"; // AIX `netstat` output is compatible with Solaris
promise = async family => {
const {stdout} = await execa("ip", args[family]);
return parse(stdout, family);
};
sync = family => {
const {stdout} = execaSync("ip", args[family]);
return parse(stdout, family);
};
} else if (plat === "darwin") {
const args = {
v4: ["-rn", "-f", "inet"],
v6: ["-rn", "-f", "inet6"],
};
// The IPv4 gateway is in column 3 in Darwin 19 (macOS 10.15 Catalina) and higher,
// previously it was in column 5
const v4IfaceColumn = parseInt(release()) >= 19 ? 3 : 5;
const parse = (stdout, family) => {
for (const line of (stdout || "").trim().split("\n")) {
const results = line.split(/ +/) || [];
const target = results[0];
const gateway = results[1];
const iface = results[family === "v4" ? v4IfaceColumn : 3];
if (dests.has(target) && gateway && isIP(gateway)) {
return {gateway, int: (iface ?? null)};
}
}
throw new Error("Unable to determine default gateway");
};
promise = async family => {
const {stdout} = await execa("netstat", args[family]);
return parse(stdout, family);
};
sync = family => {
const {stdout} = execaSync("netstat", args[family]);
return parse(stdout, family);
};
} else if (plat === "win32") {
const gwArgs = "path Win32_NetworkAdapterConfiguration where IPEnabled=true get DefaultIPGateway,GatewayCostMetric,IPConnectionMetric,Index /format:table".split(" ");
const ifArgs = index => `path Win32_NetworkAdapter where Index=${index} get NetConnectionID,MACAddress /format:table`.split(" ");
const spawnOpts = {
windowsHide: true,
};
// Parsing tables like this. The final metric is GatewayCostMetric + IPConnectionMetric
//
// DefaultIPGateway GatewayCostMetric Index IPConnectionMetric
// {"1.2.3.4", "2001:db8::1"} {0, 256} 12 25
// {"2.3.4.5"} {25} 12 55
function parseGwTable(gwTable, family) { // eslint-disable-line no-inner-declarations
let [bestGw, bestMetric, bestId] = [null, null, null];
for (let line of (gwTable || "").trim().split(/\r?\n/).splice(1)) {
line = line.trim();
const [_, gwArr, gwCostsArr, id, ipMetric] = /({.+?}) +({.+?}) +([0-9]+) +([0-9]+)/.exec(line) || [];
if (!gwArr) continue;
const gateways = (gwArr.match(/"(.+?)"/g) || []).map(match => match.substring(1, match.length - 1));
const gatewayCosts = (gwCostsArr.match(/[0-9]+/g) || []);
for (const [index, gateway] of Object.entries(gateways)) {
if (!gateway || `v${isIP(gateway)}` !== family) continue;
const metric = parseInt(gatewayCosts[index]) + parseInt(ipMetric);
if (!bestGw || metric < bestMetric) {
[bestGw, bestMetric, bestId] = [gateway, metric, id];
}
}
}
if (bestGw) return [bestGw, bestId];
}
const m = require(`./${file}.js`);
module.exports.v4 = () => m.v4();
module.exports.v6 = () => m.v6();
module.exports.v4.sync = () => m.v4.sync();
module.exports.v6.sync = () => m.v6.sync();
function parseIfTable(ifTable) { // eslint-disable-line no-inner-declarations
const line = (ifTable || "").trim().split("\n")[1];
let [mac, name] = line.trim().split(/\s+/);
mac = mac.toLowerCase();
// try to get the interface name by matching the mac to os.networkInterfaces to avoid wmic's encoding issues
// https://github.com/silverwind/default-gateway/issues/14
for (const [osname, addrs] of Object.entries(networkInterfaces())) {
for (const addr of addrs) {
if (addr && addr.mac && addr.mac.toLowerCase() === mac) {
return osname;
}
}
}
return name;
}
promise = async family => {
const {stdout} = await execa("wmic", gwArgs, spawnOpts);
const [gateway, id] = parseGwTable(stdout, family) || [];
if (!gateway) throw new Error("Unable to determine default gateway");
let name;
if (id) {
const {stdout} = await execa("wmic", ifArgs(id), spawnOpts);
name = parseIfTable(stdout);
}
return {gateway, int: name ?? null};
};
sync = family => {
const {stdout} = execaSync("wmic", gwArgs, spawnOpts);
const [gateway, id] = parseGwTable(stdout, family) || [];
if (!gateway) throw new Error("Unable to determine default gateway");
let name;
if (id) {
const {stdout} = execaSync("wmic", ifArgs(id), spawnOpts);
name = parseIfTable(stdout);
}
return {gateway, int: name ?? null};
};
} else if (plat === "android") {
const args = {
v4: ["-4", "r"],
v6: ["-6", "r"],
};
const parse = stdout => {
for (const line of (stdout || "").trim().split("\n")) {
const [_, gateway, iface] = /default via (.+?) dev (.+?)( |$)/.exec(line) || [];
if (gateway && isIP(gateway)) {
return {gateway, int: (iface ?? null)};
}
}
throw new Error("Unable to determine default gateway");
};
promise = async family => {
const {stdout} = await execa("ip", args[family]);
return parse(stdout);
};
sync = family => {
const {stdout} = execaSync("ip", args[family]);
return parse(stdout);
};
} else if (plat === "freebsd") {
const args = {
v4: ["-rn", "-f", "inet"],
v6: ["-rn", "-f", "inet6"],
};
const parse = stdout => {
for (const line of (stdout || "").trim().split("\n")) {
const [target, gateway, _, iface] = line.split(/ +/) || [];
if (dests.has(target) && gateway && isIP(gateway)) {
return {gateway, int: (iface ?? null)};
}
}
throw new Error("Unable to determine default gateway");
};
promise = async family => {
const {stdout} = await execa("netstat", args[family]);
return parse(stdout);
};
sync = family => {
const {stdout} = execaSync("netstat", args[family]);
return parse(stdout);
};
} else if (plat === "aix" && type() === "OS400") {
const args = {
v4: "IPV4",
v6: "IPV6",
};
const db2util = "/QOpenSys/pkgs/bin/db2util";
const sql = "select NEXT_HOP, LOCAL_BINDING_INTERFACE from QSYS2.NETSTAT_ROUTE_INFO where ROUTE_TYPE='DFTROUTE' and NEXT_HOP!='*DIRECT' and CONNECTION_TYPE=?";
const parse = stdout => {
try {
const resultObj = JSON.parse(stdout);
const gateway = resultObj.records[0].NEXT_HOP;
const iface = resultObj.records[0].LOCAL_BINDING_INTERFACE;
return {gateway, iface};
} catch {}
throw new Error("Unable to determine default gateway");
};
promise = async family => {
const {stdout} = await execa(db2util, [sql, "-p", args[family], "-o", "json"]);
return parse(stdout);
};
sync = family => {
const {stdout} = execaSync(db2util, [sql, "-p", args[family], "-o", "json"]);
return parse(stdout);
};
} else if (plat === "openbsd") {
const args = {
v4: ["-rn", "-f", "inet"],
v6: ["-rn", "-f", "inet6"],
};
const parse = stdout => {
for (const line of (stdout || "").trim().split("\n")) {
const results = line.split(/ +/) || [];
const target = results[0];
const gateway = results[1];
const iface = results[7];
if (dests.has(target) && gateway && isIP(gateway)) {
return {gateway, int: (iface ?? null)};
}
}
throw new Error("Unable to determine default gateway");
};
promise = async family => {
const {stdout} = await execa("netstat", args[family]);
return parse(stdout);
};
sync = family => {
const {stdout} = execaSync("netstat", args[family]);
return parse(stdout);
};
} else if (plat === "sunos" || (plat === "aix" && type() !== "OS400")) {
// AIX `netstat` output is compatible with Solaris
const args = {
v4: ["-rn", "-f", "inet"],
v6: ["-rn", "-f", "inet6"],
};
const parse = stdout => {
for (const line of (stdout || "").trim().split("\n")) {
const results = line.split(/ +/) || [];
const target = results[0];
const gateway = results[1];
const iface = results[5];
if (dests.has(target) && gateway && isIP(gateway)) {
return {gateway, int: (iface ?? null)};
}
}
throw new Error("Unable to determine default gateway");
};
promise = async family => {
const {stdout} = await execa("netstat", args[family]);
return parse(stdout);
};
sync = family => {
const {stdout} = execaSync("netstat", args[family]);
return parse(stdout);
};
} else {
const err = new Error(`Unsupported Platform: ${plat}`);
module.exports.v4 = () => Promise.reject(err);
module.exports.v6 = () => Promise.reject(err);
module.exports.v4.sync = () => { throw err; };
module.exports.v6.sync = () => { throw err; };
promise = (_) => { throw new Error("Unsupported Platform"); };
sync = (_) => { throw new Error("Unsupported Platform"); };
}
export const gateway4async = () => promise("v4");
export const gateway6async = () => promise("v6");
export const gateway4sync = () => sync("v4");
export const gateway6sync = () => sync("v6");

39

package.json
{
"name": "default-gateway",
"version": "6.0.3",
"version": "7.0.0",
"description": "Get the default network gateway, cross-platform.",

@@ -8,35 +8,20 @@ "author": "silverwind",

"license": "BSD-2-Clause",
"main": "index.js",
"type": "module",
"exports": "./index.js",
"engines": {
"node": ">= 10"
"node": ">= 16"
},
"files": [
"index.js",
"android.js",
"darwin.js",
"freebsd.js",
"linux.js",
"openbsd.js",
"sunos.js",
"win32.js",
"ibmi.js"
"./index.js"
],
"dependencies": {
"execa": "^5.0.0"
"execa": "^7.1.1"
},
"devDependencies": {
"eslint": "7.17.0",
"eslint-config-silverwind": "27.0.0",
"jest": "26.6.3",
"updates": "11.4.2",
"versions": "8.4.4"
},
"keywords": [
"default gateway",
"network",
"default",
"gateway",
"routing",
"route"
]
"eslint": "8.42.0",
"eslint-config-silverwind": "73.0.2",
"updates": "14.1.1",
"versions": "11.0.1",
"vitest": "0.32.0"
}
}
# default-gateway
[![](https://img.shields.io/npm/v/default-gateway.svg?style=flat)](https://www.npmjs.org/package/default-gateway) [![](https://img.shields.io/npm/dm/default-gateway.svg)](https://www.npmjs.org/package/default-gateway)
[![](https://img.shields.io/npm/v/default-gateway.svg?style=flat)](https://www.npmjs.org/package/default-gateway) [![](https://img.shields.io/npm/dm/default-gateway.svg)](https://www.npmjs.org/package/default-gateway) [![](https://packagephobia.com/badge?p=default-gateway)](https://packagephobia.com/result?p=default-gateway)
Obtains the machine's default gateway through `exec` calls to OS routing interfaces.
Obtains the machine's default gateway through `exec` calls to OS routing ints.

@@ -11,42 +11,34 @@ - On Linux and Android, the `ip` command must be available (usually provided by the `iproute2` package).

## Installation
## Usage
```
$ npm i default-gateway
```
## Example
```js
const defaultGateway = require('default-gateway');
import {gateway4async, gateway4sync, gateway6async, gateway6sync} from "default-gateway";
const {gateway, interface} = await defaultGateway.v4();
// gateway = '1.2.3.4', interface = 'en1'
const {gateway, int} = await gateway4async();
// gateway = '1.2.3.4', int = 'en1'
const {gateway, interface} = await defaultGateway.v6();
// gateway = '2001:db8::1', interface = 'en2'
const {gateway, int} = await gateway6async();
// gateway = '2001:db8::1', int = 'en2'
const {gateway, interface} = defaultGateway.v4.sync();
// gateway = '1.2.3.4', interface = 'en1'
const {gateway, int} = gateway4sync();
// gateway = '1.2.3.4', int = 'en1'
const {gateway, interface} = defaultGateway.v6.sync();
// gateway = '2001:db8::1', interface = 'en2'
const {gateway, int} = gateway6sync();
// gateway = '2001:db8::1', int = 'en2'
```
## API
### defaultGateway.v4()
### defaultGateway.v6()
### defaultGateway.v4.sync()
### defaultGateway.v6.sync()
### gateway4async()
### gateway6async()
### gateway4sync()
### gateway6sync()
Returns: `result` *Object*
- `gateway`: The IP address of the default gateway.
- `interface`: The name of the interface. On Windows, this is the network adapter name.
- `int`: The name of the interface. On Windows, this is the network adapter name.
The `.v{4,6}()` methods return a Promise while the `.v{4,6}.sync()` variants will return the result synchronously.
The `gateway` property will always be defined on success, while `int` can be `null` if it cannot be determined. All methods reject/throw on unexpected conditions.
The `gateway` property will always be defined on success, while `interface` can be `null` if it cannot be determined. All methods reject/throw on unexpected conditions.
## License
© [silverwind](https://github.com/silverwind), distributed under BSD licence
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc