UNPKG

29.7 kBJavaScriptView Raw
1/*!
2 * ip.js - ip utils for bcoin
3 * Copyright (c) 2014-2015, Fedor Indutny (MIT License).
4 * Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
5 * https://github.com/bcoin-org/bcoin
6 *
7 * Parts of this software are based on node-ip.
8 * https://github.com/indutny/node-ip
9 * Copyright (c) 2012, Fedor Indutny (MIT License).
10 */
11
12/* eslint no-unreachable: "off" */
13/* eslint spaced-comment: "off" */
14
15'use strict';
16
17const assert = require('bsert');
18const os = require('os');
19const base32 = require('bs32');
20const inet = require('./inet');
21const onion = require('./onion');
22const binet = exports;
23
24/*
25 * Constants
26 */
27
28const ZERO_IP = Buffer.from('00000000000000000000000000000000', 'hex');
29const LOCAL_IP = Buffer.from('00000000000000000000000000000001', 'hex');
30const RFC6052 = Buffer.from('0064ff9b0000000000000000', 'hex');
31const RFC4862 = Buffer.from('fe80000000000000', 'hex');
32const RFC6145 = Buffer.from('0000000000000000ffff0000', 'hex');
33const SHIFTED = Buffer.from('00000000000000ffff', 'hex');
34const TOR_ONION = Buffer.from('fd87d87eeb43', 'hex');
35const ZERO_KEY = Buffer.alloc(33, 0x00);
36const POOL = Buffer.alloc(16, 0x00);
37const POOLX = Buffer.alloc(16, 0x00);
38const POOLY = Buffer.alloc(16, 0x00);
39
40const ALL = 0;
41const LOCAL = 1;
42const NONLOCAL = 2;
43const PRIVATE = 3;
44const PUBLIC = 4;
45
46/**
47 * Address types.
48 * @enum {Number}
49 */
50
51const types = {
52 NONE: 0,
53 INET4: 4,
54 INET6: 6,
55 ONION: 10
56};
57
58/**
59 * Address networks.
60 * @enum {Number}
61 */
62
63const networks = {
64 NONE: 0,
65 INET4: 1,
66 INET6: 2,
67 ONION: 3,
68 TEREDO: 4
69};
70
71/**
72 * Convert a buffer to an ip string.
73 * @param {Buffer} raw
74 * @returns {String}
75 */
76
77binet.encode = function encode(raw) {
78 assert(Buffer.isBuffer(raw));
79 return binet.read(raw, 0, raw.length);
80};
81
82/**
83 * Parse an IP string and return a buffer.
84 * @param {String} str
85 * @returns {Buffer}
86 */
87
88binet.decode = function decode(str) {
89 const raw = Buffer.allocUnsafe(16);
90 binet.write(raw, str, 0, 16);
91 return raw;
92};
93
94/**
95 * Read an IP string from a buffer.
96 * @param {Buffer} raw
97 * @param {Number} [off=0]
98 * @param {Number} [size=16]
99 * @returns {String}
100 */
101
102binet.read = function read(raw, off, size) {
103 if (off == null)
104 off = 0;
105
106 if (size == null)
107 size = 16;
108
109 assert(Buffer.isBuffer(raw));
110 assert((off >>> 0) === off);
111 assert((size >>> 0) === size);
112
113 if (off + size > raw.length)
114 throw new Error('Out of bounds read.');
115
116 if (size === 4) {
117 const str = inet.ntop4(raw, off);
118
119 if (!str)
120 throw new Error('Invalid IPv4 address.');
121
122 return str;
123 }
124
125 if (size === 16) {
126 if (inet.onion(raw, off)) {
127 const on = raw.slice(off + 6, off + 16);
128 const str = onion.encodeLegacy(on);
129 return str;
130 }
131
132 let str;
133
134 if (inet.mapped(raw, off))
135 str = inet.ntop4(raw, off + 12);
136 else
137 str = inet.ntop6(raw, off);
138
139 if (!str)
140 throw new Error('Invalid IPv6 address.');
141
142 return str;
143 }
144
145 throw new Error('Invalid IP address.');
146};
147
148/**
149 * Write an IP string to a buffer.
150 * @param {Buffer} dst
151 * @param {String} str
152 * @param {Number} [off=0]
153 * @param {Number} [size=16]
154 * @returns {Number}
155 */
156
157binet.write = function write(dst, str, off, size) {
158 if (off == null)
159 off = 0;
160
161 if (size == null)
162 size = 16;
163
164 assert(Buffer.isBuffer(dst));
165 assert(typeof str === 'string');
166 assert((off >>> 0) === off);
167 assert((size >>> 0) === size);
168
169 if (off + size > dst.length)
170 throw new Error('Out of bounds write.');
171
172 if (size === 4) {
173 if (inet.pton4(str, dst, off) >= 0)
174 return off + 4;
175
176 const raw = POOL;
177
178 if (inet.pton6(str, raw, 0) < 0)
179 throw new Error('Invalid IPv4 address.');
180
181 if (!inet.mapped(raw, 0))
182 throw new Error('Out of bounds write.');
183
184 off += raw.copy(dst, off, 12, 16);
185
186 return off;
187 }
188
189 if (size === 16) {
190 if (onion.isLegacyString(str)) {
191 const prefix = TOR_ONION;
192 const data = onion.decodeLegacy(str);
193
194 off += prefix.copy(dst, off);
195 off += data.copy(dst, off);
196
197 return off;
198 }
199
200 if (inet.pton4(str, dst, off + 12) >= 0) {
201 dst.fill(0x00, off, off + 10);
202 off += 10;
203 dst[off++] = 0xff;
204 dst[off++] = 0xff;
205 return off;
206 }
207
208 if (inet.pton6(str, dst, off) >= 0)
209 return off + 16;
210
211 throw new Error('Invalid IPv6 address.');
212 }
213
214 throw new Error('Invalid IP address.');
215};
216
217/**
218 * Write an IP string to a buffer writer.
219 * @param {BufferWriter} bw
220 * @param {String} str
221 * @param {Number} [size=16]
222 * @returns {BufferWriter}
223 */
224
225binet.writeBW = function writeBW(bw, str, size) {
226 assert(bw && typeof bw === 'object');
227 bw.offset = binet.write(bw.data, str, bw.offset, size);
228 return bw;
229};
230
231/**
232 * Read an IP string from a buffer reader.
233 * @param {BufferReader} br
234 * @param {Number} [size=16]
235 * @returns {String}
236 */
237
238binet.readBR = function readBR(br, size) {
239 if (size == null)
240 size = 16;
241
242 assert(br && typeof br === 'object');
243
244 const str = binet.read(br.data, br.offset, size);
245
246 br.offset += size;
247
248 return str;
249};
250
251/**
252 * Normalize an ip.
253 * @param {String} str
254 * @returns {String}
255 */
256
257binet.normalize = function normalize(str) {
258 if (onion.isLegacyString(str))
259 return onion.normalizeLegacy(str);
260
261 const raw = POOL;
262
263 if (inet.pton4(str, raw, 0) >= 0)
264 return inet.ntop4(raw, 0);
265
266 if (inet.pton6(str, raw, 0) >= 0) {
267 if (binet.isMapped(raw))
268 return inet.ntop4(raw, 12);
269 return inet.ntop6(raw, 0);
270 }
271
272 throw new Error('Invalid IP address.');
273};
274
275/**
276 * Convert 4 byte ip address
277 * to IPv4 mapped IPv6 address.
278 * @param {Buffer} raw
279 * @returns {Buffer}
280 */
281
282binet.map = function map(raw) {
283 assert(Buffer.isBuffer(raw));
284
285 if (raw.length === 16)
286 return raw;
287
288 if (raw.length !== 4)
289 throw new Error('Not an IPv4 address.');
290
291 const data = Buffer.allocUnsafe(16);
292
293 data.fill(0x00, 0, 10);
294
295 data[10] = 0xff;
296 data[11] = 0xff;
297
298 raw.copy(data, 12);
299
300 return data;
301};
302
303/**
304 * Convert 16 byte ip address
305 * from a IPv4 mapped IPv6 address.
306 * @param {Buffer} raw
307 * @returns {Buffer}
308 */
309
310binet.unmap = function unmap(raw) {
311 assert(Buffer.isBuffer(raw));
312
313 if (raw.length === 4)
314 return raw;
315
316 if (raw.length !== 16)
317 throw new Error('Not an IPv6 address.');
318
319 if (!binet.isMapped(raw))
320 throw new Error('Not an IPv4 mapped address.');
321
322 return raw.slice(12, 16);
323};
324
325/**
326 * Concatenate a host and port.
327 * @param {String} host
328 * @param {Number} port
329 * @param {Buffer|null} key
330 * @returns {String}
331 */
332
333binet.toHost = function toHost(host, port, key) {
334 if (key == null)
335 key = null;
336
337 assert(typeof host === 'string');
338 assert((port & 0xffff) === port);
339 assert(key === null || Buffer.isBuffer(key));
340 assert(!key || key.length === 33);
341
342 if (host.length === 0)
343 throw new Error('Invalid host (zero length).');
344
345 if (host.length > 255 + 1 + 5)
346 throw new Error('Invalid host (too large).');
347
348 let colon = false;
349
350 for (let i = 0; i < host.length; i++) {
351 const ch = host.charCodeAt(i);
352
353 switch (ch) {
354 case 0x3a /*:*/:
355 colon = true;
356 break;
357 case 0x40 /*@*/:
358 case 0x5b /*[*/:
359 case 0x5d /*]*/:
360 throw new Error('Bad host.');
361 default:
362 if (ch < 0x20 || ch > 0x7e)
363 throw new Error('Bad host.');
364 break;
365 }
366 }
367
368 if (colon) {
369 if (inet.pton6(host, null, 0) < 0)
370 throw new Error('Unexpected colon.');
371 }
372
373 const type = binet.getTypeString(host);
374
375 if (type !== types.NONE)
376 host = binet.normalize(host);
377
378 let prefix = '';
379
380 if (key && !key.equals(ZERO_KEY))
381 prefix = `${base32.encode(key)}@`;
382
383 if (type === types.INET6)
384 return `${prefix}[${host}]:${port}`;
385
386 return `${prefix}${host}:${port}`;
387};
388
389/**
390 * Parse a hostname.
391 * @param {String} addr
392 * @param {Number?} fport - Fallback port.
393 * @param {Buffer?} fkey - Fallback key.
394 * @returns {Object} Contains `host`, `port`, and `type`.
395 */
396
397binet.fromHost = function fromHost(addr, fport, fkey) {
398 if (fport == null)
399 fport = 0;
400
401 if (fkey == null)
402 fkey = null;
403
404 assert(typeof addr === 'string');
405 assert((fport & 0xffff) === fport);
406 assert(fkey === null || Buffer.isBuffer(fkey));
407
408 if (addr.length === 0)
409 throw new Error('Invalid host (zero length).');
410
411 if (addr.length > 53 + 1 + 255 + 1 + 5)
412 throw new Error('Invalid host (too large).');
413
414 if (fkey && fkey.length !== 33)
415 throw new Error('Invalid fallback key (bad size).');
416
417 let key = fkey;
418 let host = '';
419 let port = null;
420 let inet6 = false;
421
422 const at = addr.indexOf('@');
423
424 if (at !== -1) {
425 const front = addr.substring(0, at);
426 const back = addr.substring(at + 1);
427
428 if (front.length > 53)
429 throw new Error('Invalid identity key (too large).');
430
431 key = base32.decode(front);
432
433 if (key.length !== 33)
434 throw new Error('Invalid identity key (bad size).');
435
436 addr = back;
437 }
438
439 if (addr[0] === '[') {
440 if (addr[addr.length - 1] === ']') {
441 // Case:
442 // [::1]
443 host = addr.slice(1, -1);
444 port = null;
445 inet6 = true;
446 } else {
447 // Case:
448 // [::1]:80
449 const colon = addr.indexOf(']:');
450
451 if (colon === -1)
452 throw new Error('IPv6 bracket mismatch.');
453
454 host = addr.substring(1, colon);
455 port = addr.substring(colon + 2);
456 inet6 = true;
457 }
458 } else {
459 const colon = addr.indexOf(':');
460
461 if (colon !== -1) {
462 const front = addr.substring(0, colon);
463 const back = addr.substring(colon + 1);
464
465 if (back.indexOf(':') !== -1) {
466 // Case:
467 // ::1
468 host = addr;
469 port = null;
470 inet6 = true;
471 } else {
472 // Cases:
473 // 127.0.0.1:80
474 // localhost:80
475 host = front;
476 port = back;
477 }
478 } else {
479 // Cases:
480 // 127.0.0.1
481 // localhost
482 host = addr;
483 port = null;
484 }
485 }
486
487 if (host.length === 0)
488 throw new Error('Invalid host (zero length).');
489
490 if (port != null) {
491 let word = 0;
492 let total = 0;
493
494 for (let i = 0; i < port.length; i++) {
495 const ch = port.charCodeAt(i);
496
497 if (ch < 0x30 || ch > 0x39)
498 throw new Error('Invalid port (bad character).');
499
500 if (total > 0 && word === 0)
501 throw new Error('Invalid port (leading zero).');
502
503 word *= 10;
504 word += ch - 0x30;
505 total += 1;
506
507 if (total > 5 || word > 0xffff)
508 throw new Error('Invalid port (overflow).');
509 }
510
511 if (total === 0)
512 throw new Error('Invalid port (bad size).');
513
514 port = word;
515 } else {
516 port = fport;
517 }
518
519 if (inet6) {
520 if (inet.pton6(host, null, 0) < 0)
521 throw new Error('Invalid IPv6 address.');
522 }
523
524 let raw = null;
525 let type = types.NONE;
526 let hostname;
527
528 try {
529 raw = binet.decode(host);
530 } catch (e) {
531 ;
532 }
533
534 if (raw) {
535 host = binet.encode(raw);
536 type = binet.getType(raw);
537 }
538
539 if (type === types.INET6)
540 hostname = `[${host}]:${port}`;
541 else
542 hostname = `${host}:${port}`;
543
544 return {
545 host,
546 port,
547 type,
548 hostname,
549 raw,
550 key
551 };
552};
553
554/**
555 * Get address type (0=none, 4=inet4, 6=inet6, 10=tor).
556 * @param {String} str
557 * @returns {Number}
558 */
559
560binet.getTypeString = function getTypeString(str) {
561 assert(typeof str === 'string');
562
563 if (str.length === 0)
564 return types.NONE;
565
566 if (str.length > 255)
567 return types.NONE;
568
569 if (onion.isLegacyString(str))
570 return types.ONION;
571
572 if (inet.pton4(str, null, 0) >= 0)
573 return types.INET4;
574
575 const raw = POOL;
576
577 if (inet.pton6(str, raw, 0) >= 0)
578 return binet.getType(raw);
579
580 return types.NONE;
581};
582
583/**
584 * Test whether a string is IPv4 mapped.
585 * @param {String} str
586 * @returns {Boolean}
587 */
588
589binet.isMappedString = function isMappedString(str) {
590 const raw = POOL;
591
592 if (inet.pton6(str, raw, 0) >= 0) {
593 if (binet.isMapped(raw))
594 return true;
595 }
596
597 return false;
598};
599
600/**
601 * Test whether a string is IPv4.
602 * @param {String} str
603 * @returns {Boolean}
604 */
605
606binet.isIPv4String = function isIPv4String(str) {
607 return binet.getTypeString(str) === types.INET4;
608};
609
610/**
611 * Test whether a string is IPv6.
612 * @param {String} str
613 * @returns {Boolean}
614 */
615
616binet.isIPv6String = function isIPv6String(str) {
617 return binet.getTypeString(str) === types.INET6;
618};
619
620/**
621 * Test whether a string is an onion address.
622 * @param {String} str
623 * @returns {Boolean}
624 */
625
626binet.isOnionString = function isOnionString(str) {
627 return binet.getTypeString(str) === types.ONION;
628};
629
630/**
631 * Test whether a string is a domain name.
632 * @param {String} str
633 * @returns {Boolean}
634 */
635
636binet.isUnknownString = function isUnknownString(str) {
637 return binet.getTypeString(str) === types.NONE;
638};
639
640/**
641 * Test whether a string is IPv4 or IPv6.
642 * @param {String} str
643 * @returns {Number}
644 */
645
646binet.isIPString = function isIPString(str) {
647 const type = binet.getTypeString(str);
648
649 switch (type) {
650 case types.INET4:
651 case types.INET6:
652 return type;
653 default:
654 return types.NONE;
655 }
656};
657
658/**
659 * Test whether two IPs are equal.
660 * @param {String} a
661 * @param {String} b
662 * @returns {Boolean}
663 */
664
665binet.isEqualString = function isEqualString(a, b) {
666 const x = POOLX;
667 const y = POOLY;
668
669 binet.write(x, a, 0, 16);
670 binet.write(y, b, 0, 16);
671
672 return x.equals(y);
673};
674
675/**
676 * Apply a network mask to IP.
677 * @param {String} str
678 * @param {String} mask
679 * @returns {Buffer}
680 */
681
682binet.maskString = function maskString(str, mask) {
683 const x = POOLX;
684 const y = POOLY;
685
686 binet.write(x, str, 0, 16);
687 binet.write(y, mask, 0, 16);
688 binet.mask(x, y, x);
689
690 return binet.encode(x);
691};
692
693/**
694 * Apply a network mask
695 * to IP from CIDR bits.
696 * @param {String} str
697 * @param {Number} bits
698 * @returns {Buffer}
699 */
700
701binet.cidrString = function cidrString(str, bits) {
702 const x = POOLX;
703
704 binet.write(x, str, 0, 16);
705 binet.cidr(x, bits, x);
706
707 return binet.encode(x);
708};
709
710/**
711 * Get address type.
712 * @param {Buffer} raw
713 * @returns {Number}
714 */
715
716binet.getType = function getType(raw) {
717 if (binet.isMapped(raw))
718 return types.INET4;
719
720 if (binet.isOnion(raw))
721 return types.ONION;
722
723 return types.INET6;
724};
725
726/**
727 * Test whether the address is IPv4 mapped.
728 * @param {Buffer} raw
729 * @returns {Boolean}
730 */
731
732binet.isMapped = function isMapped(raw) {
733 assert(Buffer.isBuffer(raw));
734 assert(raw.length === 16);
735 return inet.mapped(raw, 0);
736};
737
738/**
739 * Test whether the address is IPv4.
740 * @param {Buffer} raw
741 * @returns {Boolean}
742 */
743
744binet.isIPv4 = function isIPv4(raw) {
745 return binet.isMapped(raw);
746};
747
748/**
749 * Test whether the address is IPv6.
750 * @param {Buffer} raw
751 * @returns {Boolean}
752 */
753
754binet.isIPv6 = function isIPv6(raw) {
755 return !binet.isMapped(raw) && !binet.isOnion(raw);
756};
757
758/**
759 * Test whether the ip has a tor onion prefix.
760 * @param {Buffer} raw
761 * @returns {Boolean}
762 */
763
764binet.isOnion = function isOnion(raw) {
765 assert(Buffer.isBuffer(raw));
766 assert(raw.length === 16);
767 return inet.onion(raw, 0);
768};
769
770/**
771 * Test whether the address is IPv4 or IPv6.
772 * @param {Buffer} raw
773 * @returns {Number}
774 */
775
776binet.isIP = function isIP(raw) {
777 if (binet.isIPv4(raw))
778 return types.INET4;
779
780 if (binet.isIPv6(raw))
781 return types.INET6;
782
783 return types.NONE;
784};
785
786/**
787 * Test whether two IPs are equal.
788 * @param {Buffer} a
789 * @param {Buffer} b
790 * @returns {Boolean}
791 */
792
793binet.isEqual = function isEqual(a, b) {
794 assert(Buffer.isBuffer(a));
795 assert(Buffer.isBuffer(b));
796 assert(a.length === 16);
797 assert(b.length === 16);
798 return a.equals(b);
799};
800
801/**
802 * Apply a network mask to IP.
803 * @param {Buffer} raw
804 * @param {Buffer} mask
805 * @param {Buffer?} dst
806 * @returns {Buffer}
807 */
808
809binet.mask = function(raw, mask, dst) {
810 if (dst == null)
811 dst = Buffer.allocUnsafe(16);
812
813 assert(Buffer.isBuffer(raw));
814 assert(Buffer.isBuffer(mask));
815 assert(Buffer.isBuffer(dst));
816 assert(raw.length === 16);
817 assert(mask.length === 16);
818 assert(dst.length === 16);
819
820 const start = binet.isMapped(raw) ? 12 : 0;
821
822 if (raw !== dst)
823 raw.copy(dst, 0, 0, 16);
824
825 for (let i = start; i < 16; i++)
826 dst[i] = raw[i] & mask[i];
827
828 return dst;
829};
830
831/**
832 * Apply a network mask
833 * to IP from CIDR bits.
834 * @param {Buffer} raw
835 * @param {Number} bits
836 * @param {Buffer?} dst
837 * @returns {Buffer}
838 */
839
840binet.cidr = function cidr(raw, bits, dst) {
841 assert(Buffer.isBuffer(raw));
842 assert(raw.length === 16);
843 assert((bits & 0xff) === bits);
844
845 const mask = POOL;
846
847 let start = 0;
848 let max = 128;
849
850 if (binet.isMapped(raw)) {
851 start = 12;
852 max = 32;
853 mask.fill(0x00, 0, 10);
854 mask[10] = 0xff;
855 mask[11] = 0xff;
856 }
857
858 if (bits > max)
859 throw new Error('Too many CIDR bits.');
860
861 for (let i = start; i < 16; i++) {
862 let b = 8;
863
864 if (bits < 8)
865 b = bits;
866
867 bits -= b;
868
869 mask[i] = ~(0xff >> b) & 0xff;
870 }
871
872 return binet.mask(raw, mask, dst);
873};
874
875/**
876 * Test whether the host is null.
877 * @param {Buffer} raw
878 * @returns {Boolean}
879 */
880
881binet.isNull = function isNull(raw) {
882 if (binet.isIPv4(raw)) {
883 // 0.0.0.0
884 return raw[12] === 0
885 && raw[13] === 0
886 && raw[14] === 0
887 && raw[15] === 0;
888 }
889 // ::
890 return binet.isEqual(raw, ZERO_IP);
891};
892
893/**
894 * Test whether the host is a broadcast address.
895 * @param {Buffer} raw
896 * @returns {Boolean}
897 */
898
899binet.isBroadcast = function isBroadcast(raw) {
900 if (!binet.isIPv4(raw))
901 return false;
902
903 // 255.255.255.255
904 return raw[12] === 255
905 && raw[13] === 255
906 && raw[14] === 255
907 && raw[15] === 255;
908};
909
910/**
911 * Test whether the ip is RFC 1918.
912 * @param {Buffer} raw
913 * @returns {Boolean}
914 */
915
916binet.isRFC1918 = function isRFC1918(raw) {
917 if (!binet.isIPv4(raw))
918 return false;
919
920 if (raw[12] === 10)
921 return true;
922
923 if (raw[12] === 192 && raw[13] === 168)
924 return true;
925
926 if (raw[12] === 172 && (raw[13] >= 16 && raw[13] <= 31))
927 return true;
928
929 return false;
930};
931
932/**
933 * Test whether the ip is RFC 2544.
934 * @param {Buffer} raw
935 * @returns {Boolean}
936 */
937
938binet.isRFC2544 = function isRFC2544(raw) {
939 if (!binet.isIPv4(raw))
940 return false;
941
942 if (raw[12] === 198 && (raw[13] === 18 || raw[13] === 19))
943 return true;
944
945 if (raw[12] === 169 && raw[13] === 254)
946 return true;
947
948 return false;
949};
950
951/**
952 * Test whether the ip is RFC 3927.
953 * @param {Buffer} raw
954 * @returns {Boolean}
955 */
956
957binet.isRFC3927 = function isRFC3927(raw) {
958 if (!binet.isIPv4(raw))
959 return false;
960
961 if (raw[12] === 169 && raw[13] === 254)
962 return true;
963
964 return false;
965};
966
967/**
968 * Test whether the ip is RFC 6598.
969 * @param {Buffer} raw
970 * @returns {Boolean}
971 */
972
973binet.isRFC6598 = function isRFC6598(raw) {
974 if (!binet.isIPv4(raw))
975 return false;
976
977 if (raw[12] === 100
978 && (raw[13] >= 64 && raw[13] <= 127)) {
979 return true;
980 }
981
982 return false;
983};
984
985/**
986 * Test whether the ip is RFC 5737.
987 * @param {Buffer} raw
988 * @returns {Boolean}
989 */
990
991binet.isRFC5737 = function isRFC5737(raw) {
992 if (!binet.isIPv4(raw))
993 return false;
994
995 if (raw[12] === 192
996 && (raw[13] === 0 && raw[14] === 2)) {
997 return true;
998 }
999
1000 if (raw[12] === 198 && raw[13] === 51 && raw[14] === 100)
1001 return true;
1002
1003 if (raw[12] === 203 && raw[13] === 0 && raw[14] === 113)
1004 return true;
1005
1006 return false;
1007};
1008
1009/**
1010 * Test whether the ip is RFC 3849.
1011 * @param {Buffer} raw
1012 * @returns {Boolean}
1013 */
1014
1015binet.isRFC3849 = function isRFC3849(raw) {
1016 assert(Buffer.isBuffer(raw));
1017 assert(raw.length === 16);
1018
1019 if (raw[0] === 0x20 && raw[1] === 0x01
1020 && raw[2] === 0x0d && raw[3] === 0xb8) {
1021 return true;
1022 }
1023
1024 return false;
1025};
1026
1027/**
1028 * Test whether the ip is RFC 3964.
1029 * @param {Buffer} raw
1030 * @returns {Boolean}
1031 */
1032
1033binet.isRFC3964 = function isRFC3964(raw) {
1034 assert(Buffer.isBuffer(raw));
1035 assert(raw.length === 16);
1036
1037 if (raw[0] === 0x20 && raw[1] === 0x02)
1038 return true;
1039
1040 return false;
1041};
1042
1043/**
1044 * Test whether the ip is RFC 6052.
1045 * @param {Buffer} raw
1046 * @returns {Boolean}
1047 */
1048
1049binet.isRFC6052 = function isRFC6052(raw) {
1050 return hasPrefix(raw, RFC6052);
1051};
1052
1053/**
1054 * Test whether the ip is RFC 4380.
1055 * @param {Buffer} raw
1056 * @returns {Boolean}
1057 */
1058
1059binet.isRFC4380 = function isRFC4380(raw) {
1060 assert(Buffer.isBuffer(raw));
1061 assert(raw.length === 16);
1062
1063 if (raw[0] === 0x20 && raw[1] === 0x01
1064 && raw[2] === 0x00 && raw[3] === 0x00) {
1065 return true;
1066 }
1067
1068 return false;
1069};
1070
1071/**
1072 * Test whether the ip is RFC 4862.
1073 * @param {Buffer} raw
1074 * @returns {Boolean}
1075 */
1076
1077binet.isRFC4862 = function isRFC4862(raw) {
1078 return hasPrefix(raw, RFC4862);
1079};
1080
1081/**
1082 * Test whether the ip is RFC 4193.
1083 * @param {Buffer} raw
1084 * @returns {Boolean}
1085 */
1086
1087binet.isRFC4193 = function isRFC4193(raw) {
1088 assert(Buffer.isBuffer(raw));
1089 assert(raw.length === 16);
1090
1091 if ((raw[0] & 0xfe) === 0xfc)
1092 return true;
1093
1094 return false;
1095};
1096
1097/**
1098 * Test whether the ip is RFC 6145.
1099 * @param {Buffer} raw
1100 * @returns {Boolean}
1101 */
1102
1103binet.isRFC6145 = function isRFC6145(raw) {
1104 return hasPrefix(raw, RFC6145);
1105};
1106
1107/**
1108 * Test whether the ip is RFC 4843.
1109 * @param {Buffer} raw
1110 * @returns {Boolean}
1111 */
1112
1113binet.isRFC4843 = function isRFC4843(raw) {
1114 assert(Buffer.isBuffer(raw));
1115 assert(raw.length === 16);
1116
1117 if (raw[0] === 0x20 && raw[1] === 0x01
1118 && raw[2] === 0x00 && (raw[3] & 0xf0) === 0x10) {
1119 return true;
1120 }
1121
1122 return false;
1123};
1124
1125/**
1126 * Test whether the ip is local.
1127 * @param {Buffer} raw
1128 * @returns {Boolean}
1129 */
1130
1131binet.isLocal = function isLocal(raw) {
1132 if (binet.isIPv4(raw)) {
1133 if (raw[12] === 127 && raw[13] === 0)
1134 return true;
1135 return false;
1136 }
1137
1138 if (binet.isEqual(raw, LOCAL_IP))
1139 return true;
1140
1141 return false;
1142};
1143
1144/**
1145 * Test whether the ip is a multicast address.
1146 * @param {Buffer} raw
1147 * @returns {Boolean}
1148 */
1149
1150binet.isMulticast = function isMulticast(raw) {
1151 if (binet.isIPv4(raw)) {
1152 if ((raw[12] & 0xf0) === 0xe0)
1153 return true;
1154 return false;
1155 }
1156 return raw[0] === 0xff;
1157};
1158
1159/**
1160 * Test whether the ip is valid.
1161 * @param {Buffer} raw
1162 * @returns {Boolean}
1163 */
1164
1165binet.isValid = function isValid(raw) {
1166 if (hasPrefix(raw, SHIFTED))
1167 return false;
1168
1169 if (binet.isNull(raw))
1170 return false;
1171
1172 if (binet.isBroadcast(raw))
1173 return false;
1174
1175 if (binet.isRFC3849(raw))
1176 return false;
1177
1178 return true;
1179};
1180
1181/**
1182 * Test whether the ip is routable.
1183 * @param {Buffer} raw
1184 * @returns {Boolean}
1185 */
1186
1187binet.isRoutable = function isRoutable(raw) {
1188 if (!binet.isValid(raw))
1189 return false;
1190
1191 if (binet.isRFC1918(raw))
1192 return false;
1193
1194 if (binet.isRFC2544(raw))
1195 return false;
1196
1197 if (binet.isRFC3927(raw))
1198 return false;
1199
1200 if (binet.isRFC4862(raw))
1201 return false;
1202
1203 if (binet.isRFC6598(raw))
1204 return false;
1205
1206 if (binet.isRFC5737(raw))
1207 return false;
1208
1209 if (binet.isRFC4193(raw) && !binet.isOnion(raw))
1210 return false;
1211
1212 if (binet.isRFC4843(raw))
1213 return false;
1214
1215 if (binet.isLocal(raw))
1216 return false;
1217
1218 return true;
1219};
1220
1221/**
1222 * Get addr network. Similar to
1223 * type, but includes teredo.
1224 * @param {Buffer} raw
1225 * @returns {Number}
1226 */
1227
1228binet.getNetwork = function getNetwork(raw) {
1229 if (binet.isIPv4(raw))
1230 return networks.INET4;
1231
1232 if (binet.isRFC4380(raw))
1233 return networks.TEREDO;
1234
1235 if (binet.isOnion(raw))
1236 return networks.ONION;
1237
1238 return networks.INET6;
1239};
1240
1241/**
1242 * Calculate reachable score from source to destination.
1243 * @param {Buffer} src
1244 * @param {Buffer} dest
1245 * @returns {Number} Ranges from 0-6.
1246 */
1247
1248binet.getReachability = function getReachability(src, dest) {
1249 const UNREACHABLE = 0;
1250 const DEFAULT = 1;
1251 const TEREDO = 2;
1252 const IPV6_WEAK = 3;
1253 const IPV4 = 4;
1254 const IPV6_STRONG = 5;
1255 const PRIVATE = 6;
1256
1257 if (!binet.isRoutable(src))
1258 return UNREACHABLE;
1259
1260 const srcNet = binet.getNetwork(src);
1261 const destNet = binet.getNetwork(dest);
1262
1263 switch (destNet) {
1264 case networks.IPV4:
1265 switch (srcNet) {
1266 case networks.IPV4:
1267 return IPV4;
1268 default:
1269 return DEFAULT;
1270 }
1271 break;
1272 case networks.INET6:
1273 switch (srcNet) {
1274 case networks.TEREDO:
1275 return TEREDO;
1276 case networks.IPV4:
1277 return IPV4;
1278 case networks.INET6:
1279 if (binet.isRFC3964(src)
1280 || binet.isRFC6052(src)
1281 || binet.isRFC6145(src)) {
1282 // tunnel
1283 return IPV6_WEAK;
1284 }
1285 return IPV6_STRONG;
1286 default:
1287 return DEFAULT;
1288 }
1289 break;
1290 case networks.ONION:
1291 switch (srcNet) {
1292 case networks.IPV4:
1293 return IPV4;
1294 case networks.ONION:
1295 return PRIVATE;
1296 default:
1297 return DEFAULT;
1298 }
1299 break;
1300 case networks.TEREDO:
1301 switch (srcNet) {
1302 case networks.TEREDO:
1303 return TEREDO;
1304 case networks.INET6:
1305 return IPV6_WEAK;
1306 case networks.IPV4:
1307 return IPV4;
1308 default:
1309 return DEFAULT;
1310 }
1311 break;
1312 default:
1313 switch (srcNet) {
1314 case networks.TEREDO:
1315 return TEREDO;
1316 case networks.INET6:
1317 return IPV6_WEAK;
1318 case networks.IPV4:
1319 return IPV4;
1320 case networks.ONION:
1321 return PRIVATE;
1322 default:
1323 return DEFAULT;
1324 }
1325 break;
1326 }
1327};
1328
1329/**
1330 * Get IP address from network interfaces.
1331 * @private
1332 * @param {Number} filter
1333 * @param {Number} af
1334 * @returns {String}
1335 */
1336
1337binet._interfaces = function _interfaces(filter, af) {
1338 if (typeof os.networkInterfaces !== 'function')
1339 return [];
1340
1341 assert((filter >>> 0) === filter);
1342
1343 const family = af2str(af);
1344 const interfaces = os.networkInterfaces();
1345 const result = [];
1346 const raw = POOL;
1347
1348 for (const key of Object.keys(interfaces)) {
1349 const items = interfaces[key];
1350
1351 for (const details of items) {
1352 if (family && details.family !== family)
1353 continue;
1354
1355 try {
1356 binet.write(raw, details.address, 0, 16);
1357 } catch (e) {
1358 continue;
1359 }
1360
1361 if (!binet.isValid(raw))
1362 continue;
1363
1364 switch (af) {
1365 case types.NONE: {
1366 break;
1367 }
1368 case types.INET4: {
1369 if (!binet.isIPv4(raw))
1370 continue;
1371 break;
1372 }
1373 case types.INET6: {
1374 if (binet.isIPv4(raw))
1375 continue;
1376 break;
1377 }
1378 }
1379
1380 switch (filter) {
1381 case ALL: {
1382 break;
1383 }
1384 case LOCAL: {
1385 if (!binet.isLocal(raw))
1386 continue;
1387 break;
1388 }
1389 case NONLOCAL: {
1390 if (binet.isLocal(raw))
1391 continue;
1392 break;
1393 }
1394 case PRIVATE: {
1395 if (binet.isLocal(raw))
1396 continue;
1397
1398 if (binet.isRoutable(raw))
1399 continue;
1400
1401 break;
1402 }
1403 case PUBLIC: {
1404 if (binet.isLocal(raw))
1405 continue;
1406
1407 if (!binet.isRoutable(raw))
1408 continue;
1409
1410 break;
1411 }
1412 }
1413
1414 result.push(binet.encode(raw));
1415 }
1416 }
1417
1418 return result;
1419};
1420
1421/**
1422 * Get local IP from network interfaces.
1423 * @param {String?} family - IP family name.
1424 * @returns {String}
1425 */
1426
1427binet.getInterfaces = function getInterfaces(family) {
1428 return binet._interfaces(ALL, str2af(family));
1429};
1430
1431/**
1432 * Get local IP from network interfaces.
1433 * @param {String?} family - IP family name.
1434 * @returns {String}
1435 */
1436
1437binet.getLocal = function getLocal(family) {
1438 return binet._interfaces(LOCAL, str2af(family));
1439};
1440
1441/**
1442 * Get non-local IP from network interfaces.
1443 * @param {String?} family - IP family name.
1444 * @returns {String}
1445 */
1446
1447binet.getNonlocal = function getNonlocal(family) {
1448 return binet._interfaces(NONLOCAL, str2af(family));
1449};
1450
1451/**
1452 * Get private IP from network interfaces.
1453 * @param {String?} family - IP family name.
1454 * @returns {String}
1455 */
1456
1457binet.getPrivate = function getPrivate(family) {
1458 return binet._interfaces(PRIVATE, str2af(family));
1459};
1460
1461/**
1462 * Get public IP from network interfaces.
1463 * @param {String?} family - IP family name.
1464 * @returns {String}
1465 */
1466
1467binet.getPublic = function getPublic(family) {
1468 return binet._interfaces(PUBLIC, str2af(family));
1469};
1470
1471/*
1472 * Helpers
1473 */
1474
1475function hasPrefix(raw, prefix) {
1476 assert(Buffer.isBuffer(raw));
1477 assert(Buffer.isBuffer(prefix));
1478 assert(raw.length >= prefix.length);
1479
1480 for (let i = 0; i < prefix.length; i++) {
1481 if (raw[i] !== prefix[i])
1482 return false;
1483 }
1484
1485 return true;
1486}
1487
1488function af2str(af) {
1489 assert((af >>> 0) === af);
1490
1491 switch (af) {
1492 case types.NONE:
1493 return null;
1494 case types.INET4:
1495 return 'IPv4';
1496 case types.INET6:
1497 return 'IPv6';
1498 }
1499
1500 throw new Error(`Invalid address family: ${af}.`);
1501}
1502
1503function str2af(family) {
1504 if (family == null)
1505 return types.NONE;
1506
1507 if ((family >>> 0) === family)
1508 return family;
1509
1510 assert(typeof family === 'string');
1511 assert(family.length <= 4);
1512
1513 const name = family.toLowerCase();
1514
1515 switch (name) {
1516 case 'all':
1517 return types.NONE;
1518 case 'ipv4':
1519 return types.INET4;
1520 case 'ipv6':
1521 return types.INET6;
1522 }
1523
1524 throw new Error(`Invalid address family: ${family}.`);
1525}
1526
1527/*
1528 * Aliases
1529 */
1530
1531binet.type = binet.getTypeString;
1532binet.family = binet.isIPString;
1533binet.test = binet.getTypeString;
1534binet.equal = binet.isEqualString;
1535
1536/*
1537 * Compat (deprecated)
1538 */
1539
1540types.NAME = 0;
1541types.DNS = 0;
1542types.IPV4 = 4;
1543types.IPV6 = 6;
1544
1545binet.toString = binet.encode;
1546binet.toBuffer = binet.decode;
1547binet.toMapped = binet.map;
1548binet.isNameString = binet.isUnknownString;
1549binet.hasPrefix = hasPrefix;
1550binet.getStringType = binet.getTypeString;
1551binet.isV4String = binet.isIPv4String;
1552binet.isV6String = binet.isIPv6String;
1553binet.isDNSString = binet.isUnknownString;
1554binet.fromHostname = binet.fromHost;
1555binet.toHostname = binet.toHost;
1556binet.IP = binet;
1557binet.ip = binet;
1558
1559/*
1560 * Expose
1561 */
1562
1563binet.types = types;
1564binet.networks = networks;
1565binet.ZERO_IP = ZERO_IP;
1566binet.onion = onion;
1567binet.inet = inet;