1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- long2ip = (long) ->
- a = (long & (0xff << 24)) >>> 24;
- b = (long & (0xff << 16)) >>> 16;
- c = (long & (0xff << 8)) >>> 8;
- d = long & 0xff;
- return [a, b, c, d].join('.')
-
- ip2long = (ip) ->
- b = (ip + '').split('.');
- if b.length is 0 or b.length > 4 then throw new Error('Invalid IP')
- for byte, i in b
- if isNaN parseInt(byte, 10) then throw new Error("Invalid byte: #{byte}")
- if byte < 0 or byte > 255 then throw new Error("Invalid byte: #{byte}")
- return ((b[0] or 0) << 24 | (b[1] or 0) << 16 | (b[2] or 0) << 8 | (b[3] or 0)) >>> 0
-
-
- class Netmask
- constructor: (net, mask) ->
- throw new Error("Missing `net' parameter") unless typeof net is 'string'
- unless mask
- # try to find the mask in the net (i.e.: 1.2.3.4/24 or 1.2.3.4/255.255.255.0)
- [net, mask] = net.split('/', 2)
- unless mask
- switch net.split('.').length
- when 1 then mask = 8
- when 2 then mask = 16
- when 3 then mask = 24
- when 4 then mask = 32
- else throw new Error("Invalid net address: #{net}")
-
- if typeof mask is 'string' and mask.indexOf('.') > -1
- # Compute bitmask, the netmask as a number of bits in the network portion of the address for this block (eg.: 24)
- try
- @maskLong = ip2long(mask)
- catch error
- throw new Error("Invalid mask: #{mask}")
- for i in [32..0]
- if @maskLong == (0xffffffff << (32 - i)) >>> 0
- @bitmask = i
- break
- else if mask
- # The mask was passed as bitmask, compute the mask as long from it
- @bitmask = parseInt(mask, 10)
- @maskLong = 0
- if @bitmask > 0
- @maskLong = (0xffffffff << (32 - @bitmask)) >>> 0
- else
- throw new Error("Invalid mask: empty")
-
- try
- @netLong = (ip2long(net) & @maskLong) >>> 0
- catch error
- throw new Error("Invalid net address: #{net}")
-
- throw new Error("Invalid mask for ip4: #{mask}") unless @bitmask <= 32
-
- # The number of IP address in the block (eg.: 254)
- @size = Math.pow(2, 32 - @bitmask)
- # The address of the network block as a string (eg.: 216.240.32.0)
- @base = long2ip(@netLong)
- # The netmask as a string (eg.: 255.255.255.0)
- @mask = long2ip(@maskLong)
- # The host mask, the opposite of the netmask (eg.: 0.0.0.255)
- @hostmask = long2ip(~@maskLong)
- # The first usable address of the block
- @first = if @bitmask <= 30 then long2ip(@netLong + 1) else @base
- # The last usable address of the block
- @last = if @bitmask <= 30 then long2ip(@netLong + @size - 2) else long2ip(@netLong + @size - 1)
- # The block's broadcast address: the last address of the block (eg.: 192.168.1.255)
- @broadcast = if @bitmask <= 30 then long2ip(@netLong + @size - 1)
-
- # Returns true if the given ip or netmask is contained in the block
- contains: (ip) ->
- if typeof ip is 'string' and (ip.indexOf('/') > 0 or ip.split('.').length isnt 4)
- ip = new Netmask(ip)
-
- if ip instanceof Netmask
- return @contains(ip.base) and @contains((ip.broadcast || ip.last))
- else
- return (ip2long(ip) & @maskLong) >>> 0 == ((@netLong & @maskLong)) >>> 0
-
- # Returns the Netmask object for the block which follow this one
- next: (count=1) ->
- return new Netmask(long2ip(@netLong + (@size * count)), @mask)
-
- forEach: (fn) ->
- range = [ip2long(@first)..ip2long(@last)]
- fn long2ip(long), long, index for long, index in range
-
- # Returns the complete netmask formatted as `base/bitmask`
- toString: ->
- return @base + "/" + @bitmask
-
-
- exports.ip2long = ip2long
- exports.long2ip = long2ip
- exports.Netmask = Netmask
|