1 | 'use strict';
|
2 |
|
3 | var os = require('os');
|
4 | var fs = require('fs');
|
5 | var child = require('child_process');
|
6 |
|
7 | var DEFAULT_RESOLV_FILE = '/etc/resolv.conf';
|
8 |
|
9 | function getInterfaceName() {
|
10 | var val = 'eth';
|
11 | var platform = os.platform();
|
12 | if (platform === 'darwin') {
|
13 | val = 'en';
|
14 | } else if (platform === 'win32') {
|
15 | val = null;
|
16 | }
|
17 | return val;
|
18 | }
|
19 |
|
20 | function getIfconfigCMD() {
|
21 | if (os.platform() === 'win32') {
|
22 | return 'ipconfig/all';
|
23 | }
|
24 | return '/sbin/ifconfig';
|
25 | }
|
26 |
|
27 |
|
28 |
|
29 |
|
30 | function matchName(actualFamily, expectedFamily) {
|
31 | if (expectedFamily === 'IPv4') {
|
32 | return actualFamily === 'IPv4' || actualFamily === 4;
|
33 | }
|
34 | if (expectedFamily === 'IPv6') {
|
35 | return actualFamily === 'IPv6' || actualFamily === 6;
|
36 | }
|
37 | return actualFamily === expectedFamily;
|
38 | }
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | function address(interfaceName, callback) {
|
52 | if (typeof interfaceName === 'function') {
|
53 | callback = interfaceName;
|
54 | interfaceName = null;
|
55 | }
|
56 |
|
57 | var addr = {
|
58 | ip: address.ip(interfaceName),
|
59 | ipv6: address.ipv6(interfaceName),
|
60 | mac: null
|
61 | };
|
62 | address.mac(interfaceName, function (err, mac) {
|
63 | if (mac) {
|
64 | addr.mac = mac;
|
65 | }
|
66 | callback(err, addr);
|
67 | });
|
68 | }
|
69 |
|
70 | address.interface = function (family, name) {
|
71 | var interfaces = os.networkInterfaces();
|
72 | var noName = !name;
|
73 | name = name || getInterfaceName();
|
74 | family = family || 'IPv4';
|
75 | for (var i = -1; i < 8; i++) {
|
76 | var interfaceName = name + (i >= 0 ? i : '');
|
77 | var items = interfaces[interfaceName];
|
78 | if (items) {
|
79 | for (var j = 0; j < items.length; j++) {
|
80 | var item = items[j];
|
81 | if (matchName(item.family, family)) {
|
82 | return item;
|
83 | }
|
84 | }
|
85 | }
|
86 | }
|
87 |
|
88 | if (noName) {
|
89 |
|
90 | for (var k in interfaces) {
|
91 | var items = interfaces[k];
|
92 | for (var i = 0; i < items.length; i++) {
|
93 | var item = items[i];
|
94 |
|
95 | if (matchName(item.family, family) && !item.address.startsWith('127.')) {
|
96 | return item;
|
97 | }
|
98 | }
|
99 | }
|
100 | }
|
101 | return;
|
102 | };
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | address.ip = function (interfaceName) {
|
111 | var item = address.interface('IPv4', interfaceName);
|
112 | return item && item.address;
|
113 | };
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 | address.ipv6 = function (interfaceName) {
|
122 | var item = address.interface('IPv6', interfaceName);
|
123 | return item && item.address;
|
124 | };
|
125 |
|
126 |
|
127 |
|
128 | var MAC_OSX_START_LINE = /^(\w+)\:\s+flags=/;
|
129 | var MAC_LINUX_START_LINE = /^(\w+)\s{2,}link encap:\w+/i;
|
130 |
|
131 |
|
132 |
|
133 | var MAC_RE = address.MAC_RE = /(?:ether|HWaddr)\s+((?:[a-z0-9]{2}\:){5}[a-z0-9]{2})/i;
|
134 |
|
135 |
|
136 |
|
137 | var MAC_IP_RE = address.MAC_IP_RE = /inet\s(?:addr\:)?(\d+\.\d+\.\d+\.\d+)/;
|
138 |
|
139 | function getMAC(content, interfaceName, matchIP) {
|
140 | var lines = content.split('\n');
|
141 | for (var i = 0; i < lines.length; i++) {
|
142 | var line = lines[i].trimRight();
|
143 | var m = MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line);
|
144 | if (!m) {
|
145 | continue;
|
146 | }
|
147 |
|
148 |
|
149 | var name = m[1];
|
150 | if (name.indexOf(interfaceName) !== 0) {
|
151 | continue;
|
152 | }
|
153 |
|
154 | var ip = null;
|
155 | var mac = null;
|
156 | var match = MAC_RE.exec(line);
|
157 | if (match) {
|
158 | mac = match[1];
|
159 | }
|
160 |
|
161 | i++;
|
162 | while (true) {
|
163 | line = lines[i];
|
164 | if (!line || MAC_OSX_START_LINE.exec(line) || MAC_LINUX_START_LINE.exec(line)) {
|
165 | i--;
|
166 | break;
|
167 | }
|
168 | if (!mac) {
|
169 | match = MAC_RE.exec(line);
|
170 | if (match) {
|
171 | mac = match[1];
|
172 | }
|
173 | }
|
174 |
|
175 | if (!ip) {
|
176 | match = MAC_IP_RE.exec(line);
|
177 | if (match) {
|
178 | ip = match[1];
|
179 | }
|
180 | }
|
181 |
|
182 | i++;
|
183 | }
|
184 |
|
185 | if (ip === matchIP) {
|
186 | return mac;
|
187 | }
|
188 | }
|
189 | }
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 | address.mac = function (interfaceName, callback) {
|
198 | if (typeof interfaceName === 'function') {
|
199 | callback = interfaceName;
|
200 | interfaceName = null;
|
201 | }
|
202 | interfaceName = interfaceName || getInterfaceName();
|
203 | var item = address.interface('IPv4', interfaceName);
|
204 | if (!item) {
|
205 | return callback();
|
206 | }
|
207 |
|
208 |
|
209 |
|
210 | if (!process.env.CI && (item.mac === 'ff:00:00:00:00:00' || item.mac === '00:00:00:00:00:00')) {
|
211 |
|
212 | item.mac = '';
|
213 | }
|
214 |
|
215 | if (item.mac) {
|
216 | return callback(null, item.mac);
|
217 | }
|
218 |
|
219 | child.exec(getIfconfigCMD(), {timeout: 5000}, function (err, stdout, stderr) {
|
220 | if (err || !stdout) {
|
221 | return callback(err);
|
222 | }
|
223 |
|
224 | var mac = getMAC(stdout || '', interfaceName, item.address);
|
225 | callback(null, mac);
|
226 | });
|
227 | };
|
228 |
|
229 |
|
230 | var DNS_SERVER_RE = /^nameserver\s+(\d+\.\d+\.\d+\.\d+)$/i;
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 | address.dns = function (filepath, callback) {
|
239 | if (typeof filepath === 'function') {
|
240 | callback = filepath;
|
241 | filepath = null;
|
242 | }
|
243 | filepath = filepath || DEFAULT_RESOLV_FILE;
|
244 | fs.readFile(filepath, 'utf8', function (err, content) {
|
245 | if (err) {
|
246 | return callback(err);
|
247 | }
|
248 | var servers = [];
|
249 | content = content || '';
|
250 | var lines = content.split('\n');
|
251 | for (var i = 0; i < lines.length; i++) {
|
252 | var line = lines[i].trim();
|
253 | var m = DNS_SERVER_RE.exec(line);
|
254 | if (m) {
|
255 | servers.push(m[1]);
|
256 | }
|
257 | }
|
258 |
|
259 | callback(null, servers);
|
260 | });
|
261 | };
|
262 |
|
263 | module.exports = address;
|