address.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*!
  2. * address - lib/address.js
  3. * Copyright(c) 2013 fengmk2 <fengmk2@gmail.com>
  4. * MIT Licensed
  5. */
  6. "use strict";
  7. /**
  8. * Module dependencies.
  9. */
  10. var os = require('os');
  11. var fs = require('fs');
  12. var child = require('child_process');
  13. var DEFAULT_RESOLV_FILE = '/etc/resolv.conf';
  14. var DEFAULT_INTERFACE = 'eth';
  15. var IFCONFIG_CMD = '/sbin/ifconfig';
  16. var platform = os.platform();
  17. if (platform === 'darwin') {
  18. DEFAULT_INTERFACE = 'en';
  19. } else if (platform === 'win32') {
  20. IFCONFIG_CMD = 'ipconfig';
  21. }
  22. /**
  23. * Get all addresses.
  24. *
  25. * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os.
  26. * @param {Function(err, addr)} callback
  27. * - {Object} addr {
  28. * - {String} ip
  29. * - {String} ipv6
  30. * - {String} mac
  31. * }
  32. */
  33. function address(interfaceName, callback) {
  34. if (typeof interfaceName === 'function') {
  35. callback = interfaceName;
  36. interfaceName = null;
  37. }
  38. var addr = {
  39. ip: address.ip(interfaceName),
  40. ipv6: address.ipv6(interfaceName),
  41. mac: null
  42. };
  43. address.mac(interfaceName, function (err, mac) {
  44. if (mac) {
  45. addr.mac = mac;
  46. }
  47. callback(err, addr);
  48. });
  49. }
  50. address.interface = function (family, name) {
  51. var interfaces = os.networkInterfaces();
  52. var noName = !name;
  53. name = name || DEFAULT_INTERFACE;
  54. family = family || 'IPv4';
  55. var networks;
  56. for (var i = -1; i < 8; i++) {
  57. var items = interfaces[name + (i >= 0 ? i : '')]; // support 'lo' and 'lo0'
  58. if (items) {
  59. networks = items;
  60. break;
  61. }
  62. }
  63. if (!networks || !networks.length) {
  64. if (noName) {
  65. // filter 127.0.0.1, get the first ip
  66. for (var k in interfaces) {
  67. var items = interfaces[k];
  68. for (var i = 0; i < items.length; i++) {
  69. var item = items[i];
  70. if (item.family === family && item.address !== '127.0.0.1') {
  71. return item;
  72. }
  73. }
  74. }
  75. }
  76. return;
  77. }
  78. for (var j = 0; j < networks.length; j++) {
  79. var item = networks[j];
  80. if (item.family === family) {
  81. return item;
  82. }
  83. }
  84. };
  85. /**
  86. * Get current machine IPv4
  87. *
  88. * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os.
  89. * @return {String} IP address
  90. */
  91. address.ip = function (interfaceName) {
  92. var item = address.interface('IPv4', interfaceName);
  93. return item && item.address;
  94. };
  95. /**
  96. * Get current machine IPv6
  97. *
  98. * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os.
  99. * @return {String} IP address
  100. */
  101. address.ipv6 = function (interfaceName) {
  102. var item = address.interface('IPv6', interfaceName);
  103. return item && item.address;
  104. };
  105. // osx start line 'en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500'
  106. // linux start line 'eth0 Link encap:Ethernet HWaddr 00:16:3E:00:0A:29 '
  107. var MAC_OSX_START_LINE = /^(\w+)\:\s+flags=/;
  108. var MAC_LINUX_START_LINE = /^(\w+)\s{2,}link encap:\w+/i;
  109. // ether 78:ca:39:b0:e6:7d
  110. // HWaddr 00:16:3E:00:0A:29
  111. var MAC_RE = address.MAC_RE = /(?:ether|HWaddr)\s+((?:[a-z0-9]{2}\:){5}[a-z0-9]{2})/i;
  112. // osx: inet 192.168.2.104 netmask 0xffffff00 broadcast 192.168.2.255
  113. // linux: inet addr:10.125.5.202 Bcast:10.125.15.255 Mask:255.255.240.0
  114. var MAC_IP_RE = address.MAC_IP_RE = /inet\s(?:addr\:)?(\d+\.\d+\.\d+\.\d+)/;
  115. function getMAC(content, interfaceName, matchIP) {
  116. var lines = content.split('\n');
  117. for (var i = 0; i < lines.length; i++) {
  118. var line = lines[i].trimRight();
  119. var m = MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line);
  120. if (!m) {
  121. continue;
  122. }
  123. // check interface name
  124. var name = m[1];
  125. if (name.indexOf(interfaceName) !== 0) {
  126. continue;
  127. }
  128. var ip = null;
  129. var mac = null;
  130. var match = MAC_RE.exec(line);
  131. if (match) {
  132. mac = match[1];
  133. }
  134. i++;
  135. while (true) {
  136. line = lines[i];
  137. if (!line || MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line)) {
  138. i--;
  139. break; // hit next interface, handle next interface
  140. }
  141. if (!mac) {
  142. match = MAC_RE.exec(line);
  143. if (match) {
  144. mac = match[1];
  145. }
  146. }
  147. if (!ip) {
  148. match = MAC_IP_RE.exec(line);
  149. if (match) {
  150. ip = match[1];
  151. }
  152. }
  153. i++;
  154. }
  155. if (ip === matchIP) {
  156. return mac;
  157. }
  158. }
  159. }
  160. /**
  161. * Get current machine MAC address
  162. *
  163. * @param {String} [interfaceName] interface name, default is 'eth' on linux, 'en' on mac os.
  164. * @param {Function(err, address)} callback
  165. */
  166. address.mac = function (interfaceName, callback) {
  167. if (typeof interfaceName === 'function') {
  168. callback = interfaceName;
  169. interfaceName = null;
  170. }
  171. interfaceName = interfaceName || DEFAULT_INTERFACE;
  172. var item = address.interface('IPv4', interfaceName);
  173. if (!item) {
  174. return callback();
  175. }
  176. if (item.mac) {
  177. return callback(null, item.mac);
  178. }
  179. child.exec(IFCONFIG_CMD, {timeout: 5000}, function (err, stdout, stderr) {
  180. if (err || !stdout) {
  181. return callback(err);
  182. }
  183. var mac = getMAC(stdout || '', interfaceName, item.address);
  184. callback(null, mac);
  185. });
  186. };
  187. // nameserver 172.24.102.254
  188. var DNS_SERVER_RE = /^nameserver\s+(\d+\.\d+\.\d+\.\d+)$/i;
  189. /**
  190. * Get DNS servers.
  191. *
  192. * @param {String} [filepath] resolv config file path. default is '/etc/resolv.conf'.
  193. * @param {Function(err, servers)} callback
  194. */
  195. address.dns = function (filepath, callback) {
  196. if (typeof filepath === 'function') {
  197. callback = filepath;
  198. filepath = null;
  199. }
  200. filepath = filepath || DEFAULT_RESOLV_FILE;
  201. fs.readFile(filepath, 'utf8', function (err, content) {
  202. if (err) {
  203. return callback(err);
  204. }
  205. var servers = [];
  206. content = content || '';
  207. var lines = content.split('\n');
  208. for (var i = 0; i < lines.length; i++) {
  209. var line = lines[i].trim();
  210. var m = DNS_SERVER_RE.exec(line);
  211. if (m) {
  212. servers.push(m[1]);
  213. }
  214. }
  215. callback(null, servers);
  216. });
  217. };
  218. module.exports = address;