Giter VIP home page Giter VIP logo

ipaddr.js's Introduction

ipaddr.js — an IPv6 and IPv4 address manipulation library

Build Status

ipaddr.js is a small (1.9K minified and gzipped) library for manipulating IP addresses in JavaScript environments. It runs on both CommonJS runtimes (e.g. nodejs) and in a web browser.

ipaddr.js allows you to verify and parse string representation of an IP address, match it against a CIDR range or range list, determine if it falls into some reserved ranges (examples include loopback and private ranges), and convert between IPv4 and IPv4-mapped IPv6 addresses.

Installation

npm install ipaddr.js

or

bower install ipaddr.js

Older Node support

Use 2.x release for nodejs versions 10+. Use the 1.x release for versions of nodejs older than 10.

API

ipaddr.js defines one object in the global scope: ipaddr. In CommonJS, it is exported from the module:

const ipaddr = require('ipaddr.js');

The API consists of several global methods and two classes: ipaddr.IPv6 and ipaddr.IPv4.

Global methods

There are four global methods defined: ipaddr.isValid, ipaddr.isValidCIDR, ipaddr.parse, and ipaddr.process. All of them receive a string as a single parameter.

The ipaddr.isValid method returns true if the address is a valid IPv4 or IPv6 address, and false otherwise. It does not throw any exceptions.

The ipaddr.isValidCIDR method returns true if the address is a valid IPv4 or IPv6 address in CIDR notation, and false otherwise. It does not throw any exceptions.

The ipaddr.parse method returns an object representing the IP address, or throws an Error if the passed string is not a valid representation of an IP address.

The ipaddr.process method works just like the ipaddr.parse one, but it automatically converts IPv4-mapped IPv6 addresses to their IPv4 counterparts before returning. It is useful when you have a Node.js instance listening on an IPv6 socket, and the net.ivp6.bindv6only sysctl parameter (or its equivalent on non-Linux OS) is set to 0. In this case, you can accept IPv4 connections on your IPv6-only socket, but the remote address will be mangled. Use ipaddr.process method to automatically demangle it.

Object representation

Parsing methods return an object which descends from ipaddr.IPv6 or ipaddr.IPv4. These objects share some properties, but most of them differ.

Shared properties

One can determine the type of address by calling addr.kind(). It will return either "ipv6" or "ipv4".

An address can be converted back to its string representation with addr.toString(). Note that this method:

  • does not return the original string used to create the object (in fact, there is no way of getting that string)
  • returns a compact representation (when it is applicable)

A match(range, bits) method can be used to check if the address falls into a certain CIDR range. Note that an address can be (obviously) matched only against an address of the same type.

For example:

const addr  = ipaddr.parse('2001:db8:1234::1');
const range = ipaddr.parse('2001:db8::');

addr.match(range, 32); // => true

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.

For example:

const addr = ipaddr.parse('2001:db8:1234::1');

addr.match(ipaddr.parseCIDR('2001:db8::/32')); // => true

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".

You can match against your own range list by using 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:

const rangeList = {
  documentationOnly: [ ipaddr.parse('2001:db8::'), 32 ],
  tunnelProviders: [
    [ ipaddr.parse('2001:470::'), 32 ], // he.net
    [ ipaddr.parse('2001:5c0::'), 32 ]  // freenet6
  ]
};
ipaddr.subnetMatch(ipaddr.parse('2001:470:8:66::1'), rangeList, 'unknown'); // => "tunnelProviders"

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.)

const bytes = ipaddr.parse('2a00:1450:8007::68').toByteArray(); // ipv6.google.com
bytes // => [42, 0x00, 0x14, 0x50, 0x80, 0x07, 0x00, <zeroes...>, 0x00, 0x68 ]

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.

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.

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.

IPv6 properties

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.

For example:

const addr = ipaddr.parse('2001:0db8::0001');
addr.toString(); // => '2001:db8::1'
addr.toNormalizedString(); // => '2001:db8:0:0:0:0:0:1'

The isIPv4MappedAddress() method will return true if this address is an IPv4-mapped one, and toIPv4Address() will return an IPv4 object address.

To access the underlying binary representation of the address, use addr.parts.

const addr = ipaddr.parse('2001:db8:10::1234:DEAD');
addr.parts // => [0x2001, 0xdb8, 0x10, 0, 0, 0, 0x1234, 0xdead]

A IPv6 zone index can be accessed via addr.zoneId:

const addr = ipaddr.parse('2001:db8::%eth0');
addr.zoneId // => 'eth0'

IPv4 properties

toIPv4MappedAddress() will return a corresponding IPv4-mapped IPv6 address.

To access the underlying representation of the address, use addr.octets.

const addr = ipaddr.parse('192.168.1.1');
addr.octets // => [192, 168, 1, 1]

prefixLengthFromSubnetMask() will return a CIDR prefix length for a valid IPv4 netmask or null if the netmask is not valid.

ipaddr.IPv4.parse('255.255.255.240').prefixLengthFromSubnetMask() == 28
ipaddr.IPv4.parse('255.192.164.0').prefixLengthFromSubnetMask()  == null

subnetMaskFromPrefixLength() will return an IPv4 netmask for a valid CIDR prefix length.

ipaddr.IPv4.subnetMaskFromPrefixLength(24) == '255.255.255.0'
ipaddr.IPv4.subnetMaskFromPrefixLength(29) == '255.255.255.248'

broadcastAddressFromCIDR() will return the broadcast address for a given IPv4 interface and netmask in CIDR notation.

ipaddr.IPv4.broadcastAddressFromCIDR('172.0.0.1/24') == '172.0.0.255'

networkAddressFromCIDR() will return the network address for a given IPv4 interface and netmask in CIDR notation.

ipaddr.IPv4.networkAddressFromCIDR('172.0.0.1/24') == '172.0.0.0'

Conversion

IPv4 and IPv6 can be converted bidirectionally to and from network byte order (MSB) byte arrays.

The fromByteArray() method will take an array and create an appropriate IPv4 or IPv6 object if the input satisfies the requirements. For IPv4 it has to be an array of four 8-bit values, while for IPv6 it has to be an array of sixteen 8-bit values.

For example:

const addr = ipaddr.fromByteArray([0x7f, 0, 0, 1]);
addr.toString(); // => '127.0.0.1'

or

const addr = ipaddr.fromByteArray([0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
addr.toString(); // => '2001:db8::1'

Both objects also offer a toByteArray() method, which returns an array in network byte order (MSB).

For example:

const addr = ipaddr.parse('127.0.0.1');
addr.toByteArray(); // => [0x7f, 0, 0, 1]

or

const addr = ipaddr.parse('2001:db8::1');
addr.toByteArray(); // => [0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

ipaddr.js's People

Contributors

whitequark avatar msimerson avatar axic avatar feross avatar jamesmgreene avatar kennethtran93 avatar kika avatar scop avatar johann150 avatar disconova avatar silverwind avatar trojanspike avatar galeksandrp avatar alexandre1921 avatar anchat1990 avatar jammnrose avatar claasahl avatar danbell avatar fredthomsen avatar cableray avatar borisovg avatar jeremy-code avatar jungeonkim avatar raijinsetsu avatar ginden avatar pdonias avatar rigelk avatar rgrove avatar differentreality avatar taiki-san avatar

Stargazers

 avatar Benjamin Preiss avatar Rail Batyrshin avatar Mohsen avatar  avatar Tom Matthews avatar Haixing avatar Zixin ZOU avatar George Lima avatar 张晓刚 avatar  avatar Matéo avatar Dan Imhoff avatar Girish Ramakrishnan avatar Thomas Harr avatar masx200 avatar Hayato Mizuno avatar sky91.cn avatar 0xbc avatar Yofan Niki Andara Yudha avatar  avatar Mikhail Serebryakov avatar BluDood avatar  avatar  avatar pedoc avatar Victor Gimeno avatar  avatar Tsuzuki Tsuchiya avatar  avatar  avatar Denis Rossati avatar  avatar Jason Chiang avatar Alessio Biancalana avatar RABBIT2002 avatar Bryan Helmkamp avatar Billy Rigdon avatar Neeraj Dalal avatar karyo avatar Keisuke Komeda avatar unique.mo avatar Eric Lenington avatar  avatar Fedor V avatar sxsx欧克 avatar  avatar Andrew Corbin avatar  avatar Sandalots avatar Roj avatar  avatar  avatar  avatar Anas Mazouni avatar Federico Alvarez avatar 普林 avatar  avatar v1rtl avatar Renato Montagna Junior avatar Rado Konuch avatar Salim Virani avatar GQ avatar Serhii Shyran avatar  avatar Jim avatar Shlomo avatar  avatar Cosmic Ride avatar Landon avatar robin avatar Mustafa avatar Duncan Cameron avatar  avatar Carlos  Soriano avatar Alexey Sobolev avatar Gökhan AYHAN avatar Andrew Moore avatar ZenoTian avatar axipo avatar Chris Heschong avatar Asakura Mizu avatar May avatar  avatar  avatar Pine Mizune avatar JP Blanchette avatar Charaf Rezrazi avatar  avatar fikrihakim avatar Will avatar Davit Darsalia avatar  avatar Dhanish Vijayan avatar Andre Greeff avatar mado avatar  avatar David Borges avatar Echo avatar tongben avatar

Watchers

Leon Sorokin avatar  avatar Allex avatar  avatar GuoKai avatar James Cloos avatar Sandeep Arneja avatar Stephen avatar Michael Anthony avatar Yared Getachew avatar  avatar  avatar Peter Lai avatar Bougnat12 avatar  avatar John Magdy Lotfy Kamel avatar Feats Choi avatar  avatar 김수성 avatar Philipp Huth avatar

ipaddr.js's Issues

Doesn't support SIIT

As per wikipedia:

Stateless IP/ICMP Translation (SIIT) translates between the packet header formats in IPv6 and IPv4. The SIIT method defines a class of IPv6 addresses called IPv4-translated addresses. They have the prefix ::ffff:0:0:0/96 and may be written as ::ffff:0:a.b.c.d, in which the IPv4 formatted address a.b.c.d refers to an IPv6-enabled node. The prefix was chosen to yield a zero-valued checksum to avoid changes to the transport protocol header checksum

SIIT addresses are not parsed correctly

::ffff:127.0.0.1
IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 32512, 1 ] }

should evaluate to 127.0.0.1

4to6 Address

HI, trying to use "ipaddr.js" for 4to6 addresses, and getting weird behaviour: toString() prints the wrong address. Am I doing something wrong? ipaddr.IPv6.isIPv6 does return "true", so it is indeed recognized an ipv6 address. Is there a way to get it printed in a proper format?

console.log(">>>>>", ipaddr.parse('::ffff:192.168.1.1').toString());
>>>>> ::ffff:c0a8:101

console.log(">>>>>", ipaddr.parse('::ffff:100.160.78.136').toString());
>>>>> ::ffff:64a0:4e88

IPv6 prefixLengthFromSubnetMask

I noticed this method is only there for IPv4 but missing for IPv6. Can it be added for IPv6 too? It's useful to parse subnet masks from Node.js's os.networkInterfaces(), for example:

{ address: 'fe80::1',
  netmask: 'ffff:ffff:ffff:ffff::',
  family: 'IPv6',
  mac: '00:00:00:00:00:00',
  scopeid: 1,
  internal: true }

IPv6 validation not working properly

ipaddr.isValid('2002::2:') returns true.

To compare, Python library ipaddr raises ipaddr.AddressValueError: 2002::2: for the following code (Python equivalent to the code on the first line) ipaddr.IPv6Address('2002::2:').

ipaddr.isValid('2001:0000:1234:0000:00001:C1C0:ABCD:0876') returns true.

Optional prefix size for parseCIDR

If parseCIDR is called without a prefix size, the maximum size could be used by default (subnet of size 1).

For example:

  • IPv4: parseCIDR("192.168.1.1") => [{...}, 32]
  • IPv6: parseCIDR("2001:db8:1234::1") => [{...}, 128]

"toString.call" is missing "Object.prototype" and fails in IE11

Hi whitequark,

First of all thanks for this great piece of software!

While using it inside a browser environment I found that IE11 does not support calling "toString.call".
The relevant code is in line 34:

    if rangeSubnets[0] && toString.call(rangeSubnets[0]) != '[object Array]'

The problem is that "toString" without specifying "Object::" works in Webkit and Firefox but not in IE.
Looking at "isArray" from AngularJS you'll find that their "toString" is initialized from "Object.prototype.toString" (the logic is however the same).

The following change fixed the problem:

    if rangeSubnets[0] && Object::toString.call(rangeSubnets[0]) != '[object Array]'

(All test still pass afterwards)

jk

Normalizing IPv6 CIDRs, and getting first and last effective host addresses from IPv4 and IPv6

I've come to the realization that I believe #68, #69, #70, and #75 (all related to IPv6 CIDR methods) were all likely closed due to some communication issues over mismatched terminology.

My real usage goal for them was to be able to normalize an IPv6 CIDR to use its first effective host address rather than whatever address was originally provided, much like I can already do for IPv4 CIDRs using their network address, e.g.

ipaddr.processCIDR('ac00::1/24')  // => [ ipaddr.parse('ac00::'), 24 ]

ipaddr.processCIDR('1.2.3.4/5')   // => [ ipaddr.parse('0.0.0.0'), 5 ]

As such, I'd like to add some methods to support that cause. PR forthcoming.

Failure in parsing ipv4 with leading 0

See the coffeescript code below:

coffee> ipaddr.parse '192.12.1.1'
{ octets: [ 192, 12, 1, 1 ] }
coffee> ipaddr.parse '192.012.1.1'
{ octets: [ 192, 10, 1, 1 ] }

Why is the address wrong if i add a leading 0?

[ Feature ] isLocal

Could you add new feature function "isLocal" to check if the ip is local IPV6/IPV4

Leading 0's cause parsing havoc

Hello!

I noticed that there are oddities around parsing of IPs if there are leading 0's. For example, if given an IP that looks like this: 0192.168.001.002, this get's parsed into: 1.168.1.2.

Haven't dug into the code too much. Anything off the top of your head that might be causing this behavior? Essentially, the leading 0's should be truncated.

subnetMatch cannot handle hybrid IPv4/IPv6 scenarios

Use case: I have a list with JSON-transcribed NetFlow packets. These packets include both IPv4 and IPv6 traffic and I want to aggregate them on their net. Many of the IP ranges have both an IPv4 and an IPv6 prefix.

The natural thing to do would be to build a table containing both IPv4 and IPv6 prefixes:

var table = {
  "network a": [ ipaddr.parseCIDR('123.0.0.0/24'), ipaddr.parseCIDR('2001:3243:123::/64') ],
  ...
};

However, on trying to use such a map, subnetMatch will throw errors:

Error: ipaddr: cannot match ipv4 address with non-ipv4 one
    at IPv4.ipaddr.IPv4.IPv4.match (/Users/quest/projects/external/ipaddr.js/lib/ipaddr.js:87:15)
    at Object.ipaddr.subnetMatch (/Users/quest/projects/external/ipaddr.js/lib/ipaddr.js:46:27)

Since the error is generic, it would be hard to catch this particular case without fiddly substring matching.

It seems counter-intuitive and cumbersome to have to build two separate lookup tables.

I'll be happy to supply a PR, but I realize that this behaviour has been there for 6 years and so dependencies can be expected to depend on it. Would you be open to a PR and if so, what solution would you prefer? An instanceof guard in subnetMatch or a separate subnetMatchHybrid method?

performance issue

Hello,

just performance issue, please change line 405 of parse :

if (ipaddr.IPv6.isValid(string)) {
to
if (string.indexOf(":") != -1 && ipaddr.IPv6.isValid(string)) {

because the valid test use too much performance, on dht tracker, I got 20% just on ipv6 check, after change get 20% performance improvement (on all software) !

regards.

Please use tags to release new versions

Hi,
we are going to include your module in Debian and Ubuntu.

But we have some problem here.. our automatic systems check for tags in github when look for a new release.

It seems you do not provide a tags at all.. can you please start use them?

Thanks in advance.

L.

Readme out of sync with master

The readme mentions fromByteArray() method, and I see it in the coffee script. However, it's not in the exported ipaddr object. Is this being fixed soon?

EDIT: It appears the ipaddr.js file in lib/ has not been compiled from ipaddr.coffee lately. Also, the repository's master branch is totally out of sync with the version installed from npm.

isValid('1') returns true

var ipaddr = require('ipaddr.js'),
    ip = '1';

if (ipaddr.isValid(ip)){
    var addr = ipaddr.parse(ip);
}

Error: ipaddr: ipv6 part count should be 8
at new IPv6 (/.../ipaddr.js:155:15)
at Function.ipaddr.IPv4.parse.ipaddr.IPv6.parse (/.../ipaddr.js/lib/ipaddr.js:374:12)

isValid() returns true on single digit value

Hi,

isValid() currently returns true on:

  • single digit value, like: 0, 1, 100, 1000, ...
  • also on this one: 10.168.0001.100

Aren't these supposed to be invalid format for IP ?

Thanks.

Add git release tag 0.1.9

At the moment when using shrinkwrapping our product build fails since the last version in git is 0.1.8, but npm version is 0.1.9.

Thanks!

Validate IP Range

I have a module that relies on ipaddr.js, I got a request for the ability to validate ranges. Is that possible with ipaddr.js? Be a nice extra addon.

keverw/range_check#9

Zone Index is discarded for IPv4-mapped IPv6 (transitional) addresses

Zone Index is discarded for IPv4-mapped IPv6 (transitional) addresses

var ipaddr = require('ipaddr.js')

addr = ipaddr.parse('::ff:ffff:c0a8:101%eth0')
// IPv6 { parts: [ 0, 0, 0, 0, 255, 65535, 49320, 257 ], zoneId: 'eth0' }

addr = ipaddr.parse('::ffff:c0a8:101%z')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ], zoneId: 'z' }

// This result is missing its zone index "map"
addr = ipaddr.parse('::ffff:192.168.1.1%map')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ] }

cc: @silverwind

IPv6 Zone Index is broken after processing an IPv4-mapped (transitional) address with zone index

IPv6 Zone Index is broken after processing an IPv4-mapped (transitional) address with zone index

var ipaddr = require('ipaddr.js');

cidr = ipaddr.parse('::ffff:c0a8:101%z')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ], zoneId: 'z' }

cidr = ipaddr.parse('::ff:ffff:c0a8:101%eth0')
// IPv6 { parts: [ 0, 0, 0, 0, 255, 65535, 49320, 257 ], zoneId: 'eth0' }

// Repeat the first
cidr = ipaddr.parse('::ffff:c0a8:101%z')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ], zoneId: 'z' }

cidr = ipaddr.parse('::ffff:192.168.1.1%map')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ], zoneId: 'map' }

// BROKEN!
cidr = ipaddr.parse('::ffff:c0a8:101%z')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ] }

// BROKEN!
cidr = ipaddr.parse('::ff:ffff:c0a8:101%eth0')
// IPv6 { parts: [ 0, 0, 0, 0, 255, 65535, 49320, 257 ] }

// BROKEN!
cidr = ipaddr.parse('::ffff:192.168.1.1%eth1')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ], zoneId: 'eth1' }

// So yeah, now the IPv4-mapped addresses are the ONLY ones that can manage to process zone indexes.
// Perhaps a sticky RegExp that needs its `.lastIndex` property cleared (or to be recreated every time)...?
cidr = ipaddr.parse('::ffff:192.168.1.1%z')
// IPv6 { parts: [ 0, 0, 0, 0, 0, 65535, 49320, 257 ], zoneId: 'z' }

// BROKEN!
cidr = ipaddr.parse('::ff:ffff:c0a8:101%eth0')
// IPv6 { parts: [ 0, 0, 0, 0, 255, 65535, 49320, 257 ] }

// Without zone index (fine)
cidr = ipaddr.parse('::ff:ffff:c0a8:101')
// IPv6 { parts: [ 0, 0, 0, 0, 255, 65535, 49320, 257 ] }

// BROKEN!
cidr = ipaddr.parse('::ff:ffff:c0a8:101%eth0')
// IPv6 { parts: [ 0, 0, 0, 0, 255, 65535, 49320, 257 ] }

cc: @silverwind

Some extra features in package ipaddr-buffer

I'm using ipaddr.js with node.js Buffers in a few projects so I've just made this simple wrapper because I thought Buffer integration might be tricky given ipaddr.js really wants to be browser oriented.

It is available here: https://github.com/axic/ipaddr-buffer

It does have some other features which might make sense merging:

  • endianness field in toByteArray/fromByteArray (string, 'be' or 'le', defaults to 'be' if ommitted)
  • ipaddr.fromNumber/IPv4.toNumber to convert from/to a bigendian number representation of IPv4 (e.g. 0x7f000001)
  • maybe even tryParse which accepts any type of input and tries to decide what that might be

Let me know if you think any of these should be merged and I can prepare a PR.

Typescript-file

I created a Typescript-Definition file .. so maybe you can add it in your lib (https://stackoverflow.com/questions/37210059/how-to-add-a-typescript-definition-file-to-a-npm-package).

declare module "ipaddr.js" {

    interface IParsedIp {
        kind(): "ipv4" | "ipv6"
        toString(): string
        match<T extends IParsedIp>(ipAddress: T, bits: number): boolean
        match<T extends IParsedIp>(parseIP: T): boolean
        toByteArray(): Array<number>
        isIPv4MappedAddress(): boolean
        toNormalizedString(): string
    }

    interface IParsedIPv4 extends IParsedIp {
        kind(): "ipv4"
        octets(): Array<number>
        prefixLengthFromSubnetMask(): number | null
    }

    interface IParsedIPv6 extends IParsedIp {
        kind(): "ipv6"
        toIPv4Address(): boolean
        parts(): Array<number>
    }

    // https://github.com/whitequark/ipaddr.js#global-methods
    function isValid(ipAddress: string): boolean
    function parse(ipAddress: string): IParsedIPv4 | IParsedIPv6
    function process(ipAddress: string): IParsedIPv4 | IParsedIPv6

    function parseCIDR(ipAddress: string): IParsedIPv4 | IParsedIPv6
    function fromByteArray(list: Array<number>): IParsedIp



    interface IRangeList {
        documentationOnly: Array<IParsedIPv4 | IParsedIPv6 | number>,
        tunnelProviders: Array<Array<IParsedIPv4 | IParsedIPv6 | number>>
    }
    function subnetMatch(parsedIP: IParsedIPv4 | IParsedIPv6, rangeList: IRangeList, defaultName: string): string


    let IPv4: IIpV4;
    let IPv6: IIp;

    interface IIp {
        isValid(ipAddress: string): boolean
        parse(ipAddress: string): IParsedIp
        process(ipAddress: string): IParsedIp
    }

    interface IIpV4 extends IIp {
        isValidFourPartDecimal(ipAddress: string): boolean
        subnetMaskFromPrefixLength(prefixLength:string): string
        broadcastAddressFromCIDR(CIDR:string):string
        networkAddressFromCIDR(CIDR:string):string
    }
}

Browser support intentions? ES5 support?

I'm not sure if you are aware of this but this library's browser support is actually pretty limited due to CoffeeScript compiling down into some ES2015 syntax that is not widely supported in older versions. The use of Array.prototype.fill, in particular, completely eliminates support for any version of IE or Opera, as well as some mobile browsers -- unless the consumer also utilizes some ES2015 polyfills to inject that missing method.

I would suggest that this library should either (a) mention that so consumers know they must polyfill Array.prototype.fill, or else (b) switch to not use that method at all. Personally, I would prefer the latter as the usage of fill in this module is so limited that it would be easy to just replace it with a static value like [0,0,0,0].

Thoughts? Happy to submit a PR for either.

Add real API documentation and examples

Your module has proved itself to be incredibly useful to me in my work. However, your README documentation is nearly non-existent and some of what is there is incorrect (e.g. it mentions only 3 exposed functions, then subsequently shows 2 different ones being used, and doesn't mention the myriad others). 😕

subnetMatch throws exception on empty range

Hi, I use ipaddr.js to check if ip address belongs to some of the dynamically built ip address range. This range can be empty, and in this case subnetMatch method throws exception.
Example to reproduce the problem:

var ipaddr = require('ipaddr.js'),
    ip = ipaddr.parse('1.2.3.4');

try {
    ipaddr.subnetMatch(ip, {subnet: []}, false);
} catch (e) {
    console.log('Why am i failing???', e, e.stack);
}

Of course i can solve problem with just one if statement, but such behaviour seems strange to me (i expect it just to return false).
The source of such behaviour is next lines https://github.com/whitequark/ipaddr.js/blob/master/src/ipaddr.coffee#L34-L35
So question: is this a bug, or it was done intentionally?

isValid method throws error if undefined is passed in

No check on if string is defined (or is actually a string) is done before invoking indexOf which results in throwing an unhandled error instead of returning false as would be expected

ipaddr.IPv6.isValid = (string) ->
  # Since IPv6.isValid is always called first, this shortcut
  # provides a substantial performance gain.
  if string.indexOf(":") == -1
    return false

Zone indexes lost if containing uppercase letters

Zone indexes lost if containing uppercase letters.

Example tests that fail:

test.equal( ipaddr.parse('2001:db8:f53a::1%WAT').toString(), '2001:db8:f53a::1%WAT' )
# => Currently returns '2001:db8:f53a::1'

test.equal( ipaddr.parse('2001:db8:f53a::1%sUp').toString(), '2001:db8:f53a::1%sUp' )
# => Currently returns '2001:db8:f53a::1%s'

Feature: CIDR first and last IP in a range

I'm getting a list of CIDRs and wanting to get the first and last IP address to store in the database. Any easy way to get the first and last IP using this module? I found one that could do it but v6 results would incorrectly return 255.255.255.255

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.