darwin.js 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. "use strict";
  2. const net = require("net");
  3. const os = require("os");
  4. const execa = require("execa");
  5. const dests = ["default", "0.0.0.0", "0.0.0.0/0", "::", "::/0"];
  6. const args = {
  7. v4: ["-rn", "-f", "inet"],
  8. v6: ["-rn", "-f", "inet6"],
  9. };
  10. // The IPv4 gateway is in column 3 in Darwin 19 (macOS 10.15 Catalina) and higher,
  11. // previously it was in column 5
  12. const v4IfaceColumn = parseInt(os.release()) >= 19 ? 3 : 5;
  13. const parse = (stdout, family) => {
  14. let result;
  15. (stdout || "").trim().split("\n").some(line => {
  16. const results = line.split(/ +/) || [];
  17. const target = results[0];
  18. const gateway = results[1];
  19. const iface = results[family === "v4" ? v4IfaceColumn : 3];
  20. if (dests.includes(target) && gateway && net.isIP(gateway)) {
  21. result = {gateway, interface: (iface ? iface : null)};
  22. return true;
  23. }
  24. });
  25. if (!result) {
  26. throw new Error("Unable to determine default gateway");
  27. }
  28. return result;
  29. };
  30. const promise = async family => {
  31. const {stdout} = await execa("netstat", args[family]);
  32. return parse(stdout, family);
  33. };
  34. const sync = family => {
  35. const {stdout} = execa.sync("netstat", args[family]);
  36. return parse(stdout, family);
  37. };
  38. module.exports.v4 = () => promise("v4");
  39. module.exports.v6 = () => promise("v6");
  40. module.exports.v4.sync = () => sync("v4");
  41. module.exports.v6.sync = () => sync("v6");