|
| 1 | +# ipaddr.js — an IPv6 and IPv4 address manipulation library |
| 2 | + |
| 3 | +[](https://github.com/whitequark/ipaddr.js/actions?query=workflow%3A%22CI+Tests%22) |
| 4 | + |
| 5 | +ipaddr.js is a small (1.9K minified and gzipped) library for manipulating |
| 6 | +IP addresses in JavaScript environments. It runs on both CommonJS runtimes |
| 7 | +(e.g. [nodejs]) and in a web browser. |
| 8 | + |
| 9 | +ipaddr.js allows you to verify and parse string representation of an IP |
| 10 | +address, match it against a CIDR range or range list, determine if it falls |
| 11 | +into some reserved ranges (examples include loopback and private ranges), |
| 12 | +and convert between IPv4 and IPv4-mapped IPv6 addresses. |
| 13 | + |
| 14 | +[nodejs]: http://nodejs.org |
| 15 | + |
| 16 | +## Installation |
| 17 | + |
| 18 | +`npm install ipaddr.js` |
| 19 | + |
| 20 | +or |
| 21 | + |
| 22 | +`bower install ipaddr.js` |
| 23 | + |
| 24 | +## Older Node support |
| 25 | + |
| 26 | +Use 2.x release for nodejs versions 10+. |
| 27 | +Use the 1.x release for versions of nodejs older than 10. |
| 28 | + |
| 29 | +## API |
| 30 | + |
| 31 | +ipaddr.js defines one object in the global scope: `ipaddr`. In CommonJS, |
| 32 | +it is exported from the module: |
| 33 | + |
| 34 | +```js |
| 35 | +const ipaddr = require('ipaddr.js'); |
| 36 | +``` |
| 37 | + |
| 38 | +The API consists of several global methods and two classes: ipaddr.IPv6 and ipaddr.IPv4. |
| 39 | + |
| 40 | +### Global methods |
| 41 | + |
| 42 | +There are four global methods defined: `ipaddr.isValid`, `ipaddr.isValidCIDR`, |
| 43 | +`ipaddr.parse`, and `ipaddr.process`. All of them receive a string as a single |
| 44 | +parameter. |
| 45 | + |
| 46 | +The `ipaddr.isValid` method returns `true` if the address is a valid IPv4 or |
| 47 | +IPv6 address, and `false` otherwise. It does not throw any exceptions. |
| 48 | + |
| 49 | +The `ipaddr.isValidCIDR` method returns `true` if the address is a valid IPv4 or |
| 50 | +IPv6 address in CIDR notation, and `false` otherwise. It does not throw any exceptions. |
| 51 | + |
| 52 | +The `ipaddr.parse` method returns an object representing the IP address, |
| 53 | +or throws an `Error` if the passed string is not a valid representation of an |
| 54 | +IP address. |
| 55 | + |
| 56 | +The `ipaddr.process` method works just like the `ipaddr.parse` one, but it |
| 57 | +automatically converts IPv4-mapped IPv6 addresses to their IPv4 counterparts |
| 58 | +before returning. It is useful when you have a Node.js instance listening |
| 59 | +on an IPv6 socket, and the `net.ivp6.bindv6only` sysctl parameter (or its |
| 60 | +equivalent on non-Linux OS) is set to 0. In this case, you can accept IPv4 |
| 61 | +connections on your IPv6-only socket, but the remote address will be mangled. |
| 62 | +Use `ipaddr.process` method to automatically demangle it. |
| 63 | + |
| 64 | +### Object representation |
| 65 | + |
| 66 | +Parsing methods return an object which descends from `ipaddr.IPv6` or |
| 67 | +`ipaddr.IPv4`. These objects share some properties, but most of them differ. |
| 68 | + |
| 69 | +#### Shared properties |
| 70 | + |
| 71 | +One can determine the type of address by calling `addr.kind()`. It will return |
| 72 | +either `"ipv6"` or `"ipv4"`. |
| 73 | + |
| 74 | +An address can be converted back to its string representation with `addr.toString()`. |
| 75 | +Note that this method: |
| 76 | + * does not return the original string used to create the object (in fact, there is |
| 77 | + no way of getting that string) |
| 78 | + * returns a compact representation (when it is applicable) |
| 79 | + |
| 80 | +A `match(range, bits)` method can be used to check if the address falls into a |
| 81 | +certain CIDR range. Note that an address can be (obviously) matched only against an address of the same type. |
| 82 | + |
| 83 | +For example: |
| 84 | + |
| 85 | +```js |
| 86 | +const addr = ipaddr.parse('2001:db8:1234::1'); |
| 87 | +const range = ipaddr.parse('2001:db8::'); |
| 88 | + |
| 89 | +addr.match(range, 32); // => true |
| 90 | +``` |
| 91 | + |
| 92 | +Alternatively, `match` can also be called as `match([range, bits])`. In this way, it can be used together with the `parseCIDR(string)` method, which parses an IP address together with a CIDR range. |
| 93 | + |
| 94 | +For example: |
| 95 | + |
| 96 | +```js |
| 97 | +const addr = ipaddr.parse('2001:db8:1234::1'); |
| 98 | + |
| 99 | +addr.match(ipaddr.parseCIDR('2001:db8::/32')); // => true |
| 100 | +``` |
| 101 | + |
| 102 | +A `range()` method returns one of predefined names for several special ranges defined by IP protocols. The exact names (and their respective CIDR ranges) can be looked up in the source: [IPv6 ranges] and [IPv4 ranges]. Some common ones include `"unicast"` (the default one) and `"reserved"`. |
| 103 | + |
| 104 | +You can match against your own range list by using |
| 105 | +`ipaddr.subnetMatch(address, rangeList, defaultName)` method. It can work with a mix of IPv6 or IPv4 addresses, and accepts a name-to-subnet map as the range list. For example: |
| 106 | + |
| 107 | +```js |
| 108 | +const rangeList = { |
| 109 | + documentationOnly: [ ipaddr.parse('2001:db8::'), 32 ], |
| 110 | + tunnelProviders: [ |
| 111 | + [ ipaddr.parse('2001:470::'), 32 ], // he.net |
| 112 | + [ ipaddr.parse('2001:5c0::'), 32 ] // freenet6 |
| 113 | + ] |
| 114 | +}; |
| 115 | +ipaddr.subnetMatch(ipaddr.parse('2001:470:8:66::1'), rangeList, 'unknown'); // => "tunnelProviders" |
| 116 | +``` |
| 117 | + |
| 118 | +The addresses can be converted to their byte representation with `toByteArray()`. (Actually, JavaScript mostly does not know about byte buffers. They are emulated with arrays of numbers, each in range of 0..255.) |
| 119 | + |
| 120 | +```js |
| 121 | +const bytes = ipaddr.parse('2a00:1450:8007::68').toByteArray(); // ipv6.google.com |
| 122 | +bytes // => [42, 0x00, 0x14, 0x50, 0x80, 0x07, 0x00, <zeroes...>, 0x00, 0x68 ] |
| 123 | +``` |
| 124 | + |
| 125 | +The `ipaddr.IPv4` and `ipaddr.IPv6` objects have some methods defined, too. All of them have the same interface for both protocols, and are similar to global methods. |
| 126 | + |
| 127 | +`ipaddr.IPvX.isValid(string)` can be used to check if the string is a valid address for particular protocol, and `ipaddr.IPvX.parse(string)` is the error-throwing parser. |
| 128 | + |
| 129 | +`ipaddr.IPvX.isValid(string)` uses the same format for parsing as the POSIX `inet_ntoa` function, which accepts unusual formats like `0xc0.168.1.1` or `0x10000000`. The function `ipaddr.IPv4.isValidFourPartDecimal(string)` validates the IPv4 address and also ensures that it is written in four-part decimal format. |
| 130 | + |
| 131 | +[IPv6 ranges]: https://github.com/whitequark/ipaddr.js/blob/master/lib/ipaddr.js#L530 |
| 132 | +[IPv4 ranges]: https://github.com/whitequark/ipaddr.js/blob/master/lib/ipaddr.js#L182 |
| 133 | + |
| 134 | +#### IPv6 properties |
| 135 | + |
| 136 | +Sometimes you will want to convert IPv6 not to a compact string representation (with the `::` substitution); the `toNormalizedString()` method will return an address where all zeroes are explicit. |
| 137 | + |
| 138 | +For example: |
| 139 | + |
| 140 | +```js |
| 141 | +const addr = ipaddr.parse('2001:0db8::0001'); |
| 142 | +addr.toString(); // => '2001:db8::1' |
| 143 | +addr.toNormalizedString(); // => '2001:db8:0:0:0:0:0:1' |
| 144 | +``` |
| 145 | + |
| 146 | +The `isIPv4MappedAddress()` method will return `true` if this address is an IPv4-mapped |
| 147 | +one, and `toIPv4Address()` will return an IPv4 object address. |
| 148 | + |
| 149 | +To access the underlying binary representation of the address, use `addr.parts`. |
| 150 | + |
| 151 | +```js |
| 152 | +const addr = ipaddr.parse('2001:db8:10::1234:DEAD'); |
| 153 | +addr.parts // => [0x2001, 0xdb8, 0x10, 0, 0, 0, 0x1234, 0xdead] |
| 154 | +``` |
| 155 | + |
| 156 | +A IPv6 zone index can be accessed via `addr.zoneId`: |
| 157 | + |
| 158 | +```js |
| 159 | +const addr = ipaddr.parse('2001:db8::%eth0'); |
| 160 | +addr.zoneId // => 'eth0' |
| 161 | +``` |
| 162 | + |
| 163 | +#### IPv4 properties |
| 164 | + |
| 165 | +`toIPv4MappedAddress()` will return a corresponding IPv4-mapped IPv6 address. |
| 166 | + |
| 167 | +To access the underlying representation of the address, use `addr.octets`. |
| 168 | + |
| 169 | +```js |
| 170 | +const addr = ipaddr.parse('192.168.1.1'); |
| 171 | +addr.octets // => [192, 168, 1, 1] |
| 172 | +``` |
| 173 | + |
| 174 | +`prefixLengthFromSubnetMask()` will return a CIDR prefix length for a valid IPv4 netmask or |
| 175 | +null if the netmask is not valid. |
| 176 | + |
| 177 | +```js |
| 178 | +ipaddr.IPv4.parse('255.255.255.240').prefixLengthFromSubnetMask() == 28 |
| 179 | +ipaddr.IPv4.parse('255.192.164.0').prefixLengthFromSubnetMask() == null |
| 180 | +``` |
| 181 | + |
| 182 | +`subnetMaskFromPrefixLength()` will return an IPv4 netmask for a valid CIDR prefix length. |
| 183 | + |
| 184 | +```js |
| 185 | +ipaddr.IPv4.subnetMaskFromPrefixLength(24) == '255.255.255.0' |
| 186 | +ipaddr.IPv4.subnetMaskFromPrefixLength(29) == '255.255.255.248' |
| 187 | +``` |
| 188 | + |
| 189 | +`broadcastAddressFromCIDR()` will return the broadcast address for a given IPv4 interface and netmask in CIDR notation. |
| 190 | +```js |
| 191 | +ipaddr.IPv4.broadcastAddressFromCIDR('172.0.0.1/24') == '172.0.0.255' |
| 192 | +``` |
| 193 | +`networkAddressFromCIDR()` will return the network address for a given IPv4 interface and netmask in CIDR notation. |
| 194 | +```js |
| 195 | +ipaddr.IPv4.networkAddressFromCIDR('172.0.0.1/24') == '172.0.0.0' |
| 196 | +``` |
| 197 | + |
| 198 | +#### Conversion |
| 199 | + |
| 200 | +IPv4 and IPv6 can be converted bidirectionally to and from network byte order (MSB) byte arrays. |
| 201 | + |
| 202 | +The `fromByteArray()` method will take an array and create an appropriate IPv4 or IPv6 object |
| 203 | +if the input satisfies the requirements. For IPv4 it has to be an array of four 8-bit values, |
| 204 | +while for IPv6 it has to be an array of sixteen 8-bit values. |
| 205 | + |
| 206 | +For example: |
| 207 | +```js |
| 208 | +const addr = ipaddr.fromByteArray([0x7f, 0, 0, 1]); |
| 209 | +addr.toString(); // => '127.0.0.1' |
| 210 | +``` |
| 211 | + |
| 212 | +or |
| 213 | + |
| 214 | +```js |
| 215 | +const addr = ipaddr.fromByteArray([0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) |
| 216 | +addr.toString(); // => '2001:db8::1' |
| 217 | +``` |
| 218 | + |
| 219 | +Both objects also offer a `toByteArray()` method, which returns an array in network byte order (MSB). |
| 220 | + |
| 221 | +For example: |
| 222 | +```js |
| 223 | +const addr = ipaddr.parse('127.0.0.1'); |
| 224 | +addr.toByteArray(); // => [0x7f, 0, 0, 1] |
| 225 | +``` |
| 226 | + |
| 227 | +or |
| 228 | + |
| 229 | +```js |
| 230 | +const addr = ipaddr.parse('2001:db8::1'); |
| 231 | +addr.toByteArray(); // => [0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] |
| 232 | +``` |
0 commit comments