Move iface.nim and ipnet.nim to proper place.
This commit is contained in:
parent
518d33e26c
commit
4fa5ee3c93
|
@ -1,6 +1,14 @@
|
|||
import chronos
|
||||
## Nim-LibP2P
|
||||
## Copyright (c) 2018 Status Research & Development GmbH
|
||||
## Licensed under either of
|
||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
## at your option.
|
||||
## This file may not be copied, modified, or distributed except according to
|
||||
## those terms.
|
||||
import algorithm
|
||||
from strutils import toHex
|
||||
import ipnet
|
||||
|
||||
const
|
||||
MaxAdapterAddressLength* = 8
|
||||
|
@ -221,8 +229,8 @@ type
|
|||
StatusLowerLayerDown
|
||||
|
||||
InterfaceAddress* = object
|
||||
ifaddr*: TransportAddress
|
||||
prefix*: int
|
||||
host*: TransportAddress
|
||||
net*: IpNet
|
||||
|
||||
NetworkInterface* = object
|
||||
ifIndex*: int
|
||||
|
@ -236,114 +244,31 @@ type
|
|||
maclen*: int
|
||||
addresses*: seq[InterfaceAddress]
|
||||
|
||||
proc host*(ifa: InterfaceAddress): TransportAddress =
|
||||
## Return host address for ``ifa``.
|
||||
result = ifa.ifaddr
|
||||
|
||||
template setBroadcast(b, nby, nbi) =
|
||||
if nbi == 0:
|
||||
for i in nby..<len(b):
|
||||
b[i] = 0xFF'u8
|
||||
else:
|
||||
let bcast = not cast[byte](0xFF'u8 shl (8 - nbi))
|
||||
b[nby] = b[nby] or bcast
|
||||
for i in (nby + 1)..<len(b):
|
||||
b[i] = 0xFF'u8
|
||||
|
||||
template setNetwork(b, nby, nbi) =
|
||||
if nbi == 0:
|
||||
for i in nby..<len(b):
|
||||
b[i] = 0x00'u8
|
||||
else:
|
||||
let mask = cast[byte](0xFF'u8 shl (8 - nbi))
|
||||
b[nby] = b[nby] and mask
|
||||
for i in (nby + 1)..<len(b):
|
||||
b[i] = 0x00'u8
|
||||
|
||||
template setNetmask(b, nby, nbi) =
|
||||
var mask: byte
|
||||
for i in 0..<nby:
|
||||
b[i] = 0xFF'u8
|
||||
if nbi > 0:
|
||||
mask = cast[byte](0xFF'u8 shl (8 - nbi))
|
||||
if nby < len(b):
|
||||
b[nby] = b[nby] or mask
|
||||
for i in (nby + 1)..<len(b):
|
||||
b[i] = 0x00'u8
|
||||
|
||||
proc broadcast*(ifa: InterfaceAddress): TransportAddress =
|
||||
proc broadcast*(ifa: InterfaceAddress): TransportAddress {.inline.} =
|
||||
## Return broadcast address for ``ifa``.
|
||||
let nbytes = ifa.prefix div 8
|
||||
let nbits = ifa.prefix mod 8
|
||||
result = ifa.ifaddr
|
||||
if result.family == AddressFamily.IPv4:
|
||||
setBroadcast(result.address_v4, nbytes, nbits)
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
setBroadcast(result.address_v6, nbytes, nbits)
|
||||
result = ifa.net.broadcast()
|
||||
|
||||
proc network*(ifa: InterfaceAddress): TransportAddress =
|
||||
proc network*(ifa: InterfaceAddress): TransportAddress {.inline.} =
|
||||
## Return network address for ``ifa``.
|
||||
let nbytes = ifa.prefix div 8
|
||||
let nbits = ifa.prefix mod 8
|
||||
result = ifa.ifaddr
|
||||
if result.family == AddressFamily.IPv4:
|
||||
setNetwork(result.address_v4, nbytes, nbits)
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
setNetwork(result.address_v6, nbytes, nbits)
|
||||
result = ifa.net.network()
|
||||
|
||||
proc netmask*(ifa: InterfaceAddress): TransportAddress =
|
||||
proc netmask*(ifa: InterfaceAddress): TransportAddress {.inline.} =
|
||||
## Return network mask for ``ifa``.
|
||||
let nbytes = ifa.prefix div 8
|
||||
let nbits = ifa.prefix mod 8
|
||||
result = TransportAddress(family: ifa.ifaddr.family)
|
||||
if result.family == AddressFamily.IPv4:
|
||||
setNetmask(result.address_v4, nbytes, nbits)
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
setNetmask(result.address_v6, nbytes, nbits)
|
||||
|
||||
proc hostMin*(ifa: InterfaceAddress): TransportAddress =
|
||||
## Return minimum allowed host address for ``ifa``
|
||||
result = ifa.network()
|
||||
if result.family == AddressFamily.IPv4:
|
||||
let last = len(result.address_v4) - 1
|
||||
result.address_v4[last] = result.address_v4[last] + 1
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
let last = len(result.address_v6) - 1
|
||||
result.address_v6[last] = result.address_v6[last] + 1
|
||||
|
||||
proc hostMax*(ifa: InterfaceAddress): TransportAddress =
|
||||
## Return maximum allowed host address for ``ifa``.
|
||||
result = ifa.broadcast()
|
||||
if result.family == AddressFamily.IPv4:
|
||||
let last = len(result.address_v4) - 1
|
||||
result.address_v4[last] = result.address_v4[last] - 1
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
let last = len(result.address_v6) - 1
|
||||
result.address_v6[last] = result.address_v6[last] - 1
|
||||
result = ifa.net.subnetMask()
|
||||
|
||||
proc init*(ift: typedesc[InterfaceAddress], address: TransportAddress,
|
||||
prefix: int): InterfaceAddress =
|
||||
## Initialize ``InterfaceAddress`` using ``address`` and prefix length
|
||||
## ``prefix``.
|
||||
result.ifaddr = address
|
||||
result.prefix = prefix
|
||||
result.host = address
|
||||
result.net = IpNet.init(address, prefix)
|
||||
|
||||
proc `$`*(ifa: InterfaceAddress): string =
|
||||
proc `$`*(ifa: InterfaceAddress): string {.inline.} =
|
||||
## Return string representation of ``ifa``.
|
||||
if ifa.ifaddr.family == AddressFamily.IPv4:
|
||||
var a = IpAddress(
|
||||
family: IpAddressFamily.IPv4,
|
||||
address_v4: ifa.ifaddr.address_v4
|
||||
)
|
||||
result = $a
|
||||
result.add("/")
|
||||
result.add($int(ifa.prefix))
|
||||
elif ifa.ifaddr.family == AddressFamily.IPv6:
|
||||
var a = IpAddress(family: IpAddressFamily.IPv6,
|
||||
address_v6: ifa.ifaddr.address_v6)
|
||||
result = $a
|
||||
result.add("/")
|
||||
result.add($int(ifa.prefix))
|
||||
if ifa.host.family == AddressFamily.IPv4:
|
||||
result = $ifa.net
|
||||
elif ifa.host.family == AddressFamily.IPv6:
|
||||
result = $ifa.net
|
||||
|
||||
proc `$`*(iface: NetworkInterface): string =
|
||||
## Return string representation of network interface ``iface``.
|
||||
|
@ -373,9 +298,9 @@ proc `$`*(iface: NetworkInterface): string =
|
|||
result.add(":")
|
||||
for item in iface.addresses:
|
||||
result.add("\n ")
|
||||
if item.ifaddr.family == AddressFamily.IPv4:
|
||||
if item.host.family == AddressFamily.IPv4:
|
||||
result.add("inet ")
|
||||
elif item.ifaddr.family == AddressFamily.IPv6:
|
||||
elif item.host.family == AddressFamily.IPv6:
|
||||
result.add("inet6 ")
|
||||
result.add($item)
|
||||
result.add(" netmask ")
|
||||
|
@ -745,8 +670,8 @@ when defined(linux):
|
|||
if len(result.addresses) == 0:
|
||||
result.addresses = newSeq[InterfaceAddress]()
|
||||
let prefixLength = cast[int](iaddr.ifa_prefixlen)
|
||||
result.addresses.add(InterfaceAddress(ifaddr: address,
|
||||
prefix: prefixLength))
|
||||
let ifaddr = InterfaceAddress.init(address, prefixLength)
|
||||
result.addresses.add(ifaddr)
|
||||
|
||||
proc getLinks(netfd: SocketHandle, pid: Pid): seq[NetworkInterface] =
|
||||
if not sendNetlinkMessage(netfd, pid, 1, RTM_GETLINK,
|
||||
|
@ -904,26 +829,6 @@ elif defined(macosx) or defined(bsd):
|
|||
else:
|
||||
result = StatusDown
|
||||
|
||||
proc netmaskToPrefix(address: TransportAddress): int =
|
||||
var lastbyte: byte
|
||||
if address.family == AddressFamily.IPv4:
|
||||
for i in 0..<len(address.address_v4):
|
||||
if address.address_v4[i] == 0xFF'u8:
|
||||
result += 8
|
||||
else:
|
||||
lastbyte = address.address_v4[i]
|
||||
break
|
||||
elif address.family == AddressFamily.IPv6:
|
||||
for i in 0..<len(address.address_v6):
|
||||
if address.address_v6[i] == 0xFF'u8:
|
||||
result += 8
|
||||
else:
|
||||
lastbyte = address.address_v6[i]
|
||||
break
|
||||
while lastbyte > 0'u8:
|
||||
lastbyte = lastbyte shl 1
|
||||
result += 1
|
||||
|
||||
proc getInterfaces*(): seq[NetworkInterface] =
|
||||
## Return list of available interfaces.
|
||||
var ifap: ptr IfAddrs
|
||||
|
@ -960,10 +865,10 @@ elif defined(macosx) or defined(bsd):
|
|||
result[i].mtu = cast[int](data.ifi_mtu)
|
||||
elif family == posix.AF_INET:
|
||||
fromSAddr(cast[ptr Sockaddr_storage](ifap.ifa_addr),
|
||||
Socklen(sizeof(SockAddr_in)), ifaddress.ifaddr)
|
||||
Socklen(sizeof(SockAddr_in)), ifaddress.host)
|
||||
elif family == posix.AF_INET6:
|
||||
fromSAddr(cast[ptr Sockaddr_storage](ifap.ifa_addr),
|
||||
Socklen(sizeof(SockAddr_in6)), ifaddress.ifaddr)
|
||||
Socklen(sizeof(SockAddr_in6)), ifaddress.host)
|
||||
if not isNil(ifap.ifa_netmask):
|
||||
var na: TransportAddress
|
||||
var slen: Socklen
|
||||
|
@ -974,9 +879,9 @@ elif defined(macosx) or defined(bsd):
|
|||
elif family == posix.AF_INET6:
|
||||
fromSAddr(cast[ptr Sockaddr_storage](ifap.ifa_netmask),
|
||||
Socklen(sizeof(SockAddr_in6)), na)
|
||||
ifaddress.prefix = netmaskToPrefix(na)
|
||||
ifaddress.net = IpNet.init(ifaddress.host, na)
|
||||
|
||||
if ifaddress.ifaddr.family != AddressFamily.None:
|
||||
if ifaddress.host.family != AddressFamily.None:
|
||||
if len(result[i].addresses) == 0:
|
||||
result[i].addresses = newSeq[InterfaceAddress]()
|
||||
result[i].addresses.add(ifaddress)
|
||||
|
@ -1182,7 +1087,7 @@ elif defined(windows):
|
|||
vista: bool): InterfaceAddress =
|
||||
var netfamily = ifunic.address.lpSockaddr.sa_family
|
||||
fromSAddr(cast[ptr Sockaddr_storage](ifunic.address.lpSockaddr),
|
||||
SockLen(ifunic.address.iSockaddrLength), result.ifaddr)
|
||||
SockLen(ifunic.address.iSockaddrLength), result.host)
|
||||
if not vista:
|
||||
var prefix = ifitem.firstPrefix
|
||||
var prefixLength = -1
|
||||
|
@ -1192,15 +1097,15 @@ elif defined(windows):
|
|||
fromSAddr(cast[ptr Sockaddr_storage](prefix.address.lpSockaddr),
|
||||
SockLen(prefix.address.iSockaddrLength), pa)
|
||||
if netfamily == prefamily:
|
||||
if ipMatchPrefix(result.ifaddr, pa, cast[int](prefix.prefixLength)):
|
||||
if ipMatchPrefix(result.host, pa, cast[int](prefix.prefixLength)):
|
||||
prefixLength = max(prefixLength, cast[int](prefix.prefixLength))
|
||||
prefix = prefix.next
|
||||
if prefixLength >= 0:
|
||||
result.prefix = prefixLength
|
||||
result.net = IpNet.init(result.host, prefixLength)
|
||||
else:
|
||||
let prefixLength = cast[int](ifunic.onLinkPrefixLength)
|
||||
if prefixLength >= 0:
|
||||
result.prefix = prefixLength
|
||||
result.net = IpNet.init(result.host, prefixLength)
|
||||
|
||||
proc getInterfaces*(): seq[NetworkInterface] =
|
||||
## Return list of network interfaces.
|
||||
|
@ -1254,8 +1159,3 @@ elif defined(windows):
|
|||
|
||||
else:
|
||||
{.fatal: "Sorry, your OS is currently not supported!".}
|
||||
|
||||
when isMainModule:
|
||||
var a = getInterfaces()
|
||||
for item in a:
|
||||
echo $item
|
|
@ -1,5 +1,15 @@
|
|||
## Nim-LibP2P
|
||||
## Copyright (c) 2018 Status Research & Development GmbH
|
||||
## Licensed under either of
|
||||
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
## at your option.
|
||||
## This file may not be copied, modified, or distributed except according to
|
||||
## those terms.
|
||||
|
||||
import endians, strutils
|
||||
import chronos
|
||||
export chronos
|
||||
|
||||
type
|
||||
IpMask* = object
|
||||
|
@ -44,6 +54,15 @@ proc toHostOrder(mask: IpMask): IpMask {.inline.} =
|
|||
swapEndian64(cast[pointer](addr result.mask6[1]),
|
||||
cast[pointer](unsafeAddr mask.mask6[1]))
|
||||
|
||||
proc `==`*(m1, m2: IpMask): bool {.inline.} =
|
||||
## Returns ``true`` if masks ``m1`` and ``m2`` are equal in IP family and
|
||||
## by value.
|
||||
if m1.family == m2.family:
|
||||
if m1.family == AddressFamily.IPv4:
|
||||
result = (m1.mask4 == m2.mask4)
|
||||
elif m1.family == AddressFamily.IPv6:
|
||||
result = ((m1.mask6[0] == m2.mask6[0]) and (m1.mask6[1] == m2.mask6[1]))
|
||||
|
||||
proc init*(t: typedesc[IpMask], family: AddressFamily, prefix: int): IpMask =
|
||||
## Initialize mask of IP family ``family`` from prefix length ``prefix``.
|
||||
##
|
||||
|
@ -85,7 +104,7 @@ proc init*(t: typedesc[IpMask], netmask: TransportAddress): IpMask =
|
|||
result.mask6[0] = cast[ptr uint64](unsafeAddr netmask.address_v6[0])[]
|
||||
result.mask6[1] = cast[ptr uint64](unsafeAddr netmask.address_v6[8])[]
|
||||
|
||||
proc init*(t: typedesc[IpMask], netmask: string): IpMask =
|
||||
proc initIp*(t: typedesc[IpMask], netmask: string): IpMask =
|
||||
## Initialize network mask using IPv4 or IPv6 address in text representation
|
||||
## ``netmask``.
|
||||
##
|
||||
|
@ -98,6 +117,58 @@ proc init*(t: typedesc[IpMask], netmask: string): IpMask =
|
|||
except ValueError:
|
||||
discard
|
||||
|
||||
proc init*(t: typedesc[IpMask], netmask: string): IpMask =
|
||||
## Initialize network mask using hexadecimal string representation
|
||||
## ``netmask``.
|
||||
##
|
||||
## If ``netmask`` mask is invalid, result IpMask.family will be set to
|
||||
## ``AddressFamily.None``.
|
||||
const
|
||||
hexNumbers = {'0'..'9'}
|
||||
hexCapitals = {'A'..'F'}
|
||||
hexLowers = {'a'..'f'}
|
||||
let length = len(netmask)
|
||||
if length == 8 or length == (2 + 8):
|
||||
## IPv4 mask
|
||||
var offset = 0
|
||||
if length == 2 + 8:
|
||||
offset = 2
|
||||
var res = IpMask(family: AddressFamily.IPv4)
|
||||
var r, v: uint32
|
||||
for i in 0..<8:
|
||||
if netmask[offset + i] in hexNumbers:
|
||||
v = cast[uint32](ord(netmask[offset + i]) - ord('0'))
|
||||
elif netmask[offset + i] in hexCapitals:
|
||||
v = cast[uint32](ord(netmask[offset + i]) - ord('A') + 10)
|
||||
elif netmask[offset + i] in hexLowers:
|
||||
v = cast[uint32](ord(netmask[offset + i]) - ord('a') + 10)
|
||||
else:
|
||||
return
|
||||
r = (r shl 4) or v
|
||||
bigEndian32(addr res.mask4, addr r)
|
||||
result = res
|
||||
elif length == 32 or length == (2 + 32):
|
||||
## IPv6 mask
|
||||
var offset = 0
|
||||
if length == 2 + 32:
|
||||
offset = 2
|
||||
var res = IpMask(family: AddressFamily.IPv6)
|
||||
for i in 0..1:
|
||||
var r, v: uint64
|
||||
for i in 0..<16:
|
||||
if netmask[offset + i] in hexNumbers:
|
||||
v = cast[uint64](ord(netmask[offset + i]) - ord('0'))
|
||||
elif netmask[offset + i] in hexCapitals:
|
||||
v = cast[uint64](ord(netmask[offset + i]) - ord('A') + 10)
|
||||
elif netmask[offset + i] in hexLowers:
|
||||
v = cast[uint64](ord(netmask[offset + i]) - ord('a') + 10)
|
||||
else:
|
||||
return
|
||||
r = (r shl 4) or v
|
||||
offset += 16
|
||||
bigEndian64(addr res.mask6[i], addr r)
|
||||
result = res
|
||||
|
||||
proc toIPv6*(address: TransportAddress): TransportAddress =
|
||||
## Map IPv4 ``address`` to IPv6 address.
|
||||
##
|
||||
|
@ -188,10 +259,16 @@ proc mask*(a: TransportAddress, m: IpMask): TransportAddress =
|
|||
|
||||
proc prefix*(mask: IpMask): int =
|
||||
## Returns number of bits set `1` in IP mask ``mask``.
|
||||
##
|
||||
## Procedure returns ``-1`` if mask is not canonical, e.g. has holes with
|
||||
## ``0`` bits between ``1`` bits.
|
||||
var hmask = mask.toHostOrder()
|
||||
if hmask.family == AddressFamily.IPv4:
|
||||
var n = hmask.mask4
|
||||
while n != 0:
|
||||
if (n and 0x8000_0000'u32) == 0'u32:
|
||||
result = -1
|
||||
return
|
||||
n = n shl 1
|
||||
inc(result)
|
||||
elif hmask.family == AddressFamily.IPv6:
|
||||
|
@ -202,13 +279,21 @@ proc prefix*(mask: IpMask): int =
|
|||
else:
|
||||
var n = hmask.mask6[1]
|
||||
while n != 0:
|
||||
if (n and 0x8000_0000_0000_0000'u64) == 0'u64:
|
||||
result = -1
|
||||
return
|
||||
n = n shl 1
|
||||
inc(result)
|
||||
else:
|
||||
var n = hmask.mask6[0]
|
||||
while n != 0:
|
||||
if (n and 0x8000_0000_0000_0000'u64) == 0'u64:
|
||||
result = -1
|
||||
return
|
||||
n = n shl 1
|
||||
inc(result)
|
||||
if hmask.mask6[1] != 0x00'u64:
|
||||
result = -1
|
||||
|
||||
proc subnetMask*(mask: IpMask): TransportAddress =
|
||||
## Returns TransportAddress representation of IP mask ``mask``.
|
||||
|
@ -219,12 +304,12 @@ proc subnetMask*(mask: IpMask): TransportAddress =
|
|||
cast[ptr uint64](addr result.address_v6[0])[] = mask.mask6[0]
|
||||
cast[ptr uint64](addr result.address_v6[8])[] = mask.mask6[1]
|
||||
|
||||
proc `$`*(mask: IpMask): string =
|
||||
proc `$`*(mask: IpMask, include0x = false): string =
|
||||
## Returns hexadecimal string representation of IP mask ``mask``.
|
||||
var host = mask.toHostOrder()
|
||||
result = ""
|
||||
if host.family == AddressFamily.IPv4:
|
||||
result = "0x"
|
||||
result = if include0x: "0x" else: ""
|
||||
var n = 32
|
||||
var m = host.mask4
|
||||
while n > 0:
|
||||
|
@ -235,7 +320,7 @@ proc `$`*(mask: IpMask): string =
|
|||
else:
|
||||
result.add(chr(ord('A') + (c - 10)))
|
||||
elif host.family == AddressFamily.IPv6:
|
||||
result = "0x"
|
||||
result = if include0x: "0x" else: ""
|
||||
for i in 0..1:
|
||||
var n = 64
|
||||
var m = host.mask6[i]
|
||||
|
@ -246,13 +331,28 @@ proc `$`*(mask: IpMask): string =
|
|||
result.add(chr(ord('0') + c))
|
||||
else:
|
||||
result.add(chr(ord('A') + (c - 10)))
|
||||
else:
|
||||
raise newException(ValueError, "Invalid mask")
|
||||
|
||||
proc ip*(mask: IpMask): string =
|
||||
## Returns IP address text representation of IP mask ``mask``.
|
||||
if mask.family == AddressFamily.IPv4:
|
||||
var ip = IpAddress(family: IpAddressFamily.IPv4)
|
||||
copyMem(addr ip.address_v4[0], unsafeAddr mask.mask4, sizeof(uint32))
|
||||
result = $ip
|
||||
elif mask.family == AddressFamily.IPv6:
|
||||
var ip = IpAddress(family: IpAddressFamily.IPv6)
|
||||
copyMem(addr ip.address_v6[0], unsafeAddr mask.mask6[0], 16)
|
||||
result = $ip
|
||||
else:
|
||||
raise newException(ValueError, "Invalid mask")
|
||||
|
||||
proc init*(t: typedesc[IpNet], host: TransportAddress,
|
||||
prefix: int): IpNet {.inline.} =
|
||||
## Initialize IP Network using host address ``host`` and prefix length
|
||||
## ``prefix``.
|
||||
result.mask = IpMask.init(host.family, prefix)
|
||||
result.host = mask(host, result.mask)
|
||||
result.host = host
|
||||
|
||||
proc init*(t: typedesc[IpNet], host, mask: TransportAddress): IpNet {.inline.} =
|
||||
## Initialize IP Network using host address ``host`` and network mask
|
||||
|
@ -261,25 +361,22 @@ proc init*(t: typedesc[IpNet], host, mask: TransportAddress): IpNet {.inline.} =
|
|||
## Note that ``host`` and ``mask`` must be from the same IP family.
|
||||
if host.family == mask.family:
|
||||
result.mask = IpMask.init(mask)
|
||||
result.host = mask(host, result.mask)
|
||||
result.host = host
|
||||
|
||||
proc init*(t: typedesc[IpNet], host: TransportAddress,
|
||||
mask: IpMask): IpNet {.inline.} =
|
||||
## Initialize IP Network using host address ``host`` and network mask
|
||||
## ``mask``.
|
||||
result.mask = mask
|
||||
result.host = result.mask(host)
|
||||
result.host = host
|
||||
|
||||
proc init*(t: typedesc[IpNet], network: string): IpNet =
|
||||
## Initialize IP Network from string representation in format
|
||||
## <address>/<prefix length>.
|
||||
##
|
||||
## Not if <prefix length> is not present or its value is bigger then maximum
|
||||
## value (32 for IPv4 and 128 for IPv6), then `/32` and `/128` will be used
|
||||
## as prefix length.
|
||||
## <address>/<prefix length> or <address>/<netmask address>.
|
||||
var parts = network.rsplit("/", maxsplit = 1)
|
||||
var host: TransportAddress
|
||||
var host, mhost: TransportAddress
|
||||
var ipaddr: IpAddress
|
||||
var mask: IpMask
|
||||
var prefix: int
|
||||
try:
|
||||
ipaddr = parseIpAddress(parts[0])
|
||||
|
@ -292,50 +389,87 @@ proc init*(t: typedesc[IpNet], network: string): IpNet =
|
|||
host.address_v6 = ipaddr.address_v6
|
||||
prefix = 128
|
||||
if len(parts) > 1:
|
||||
prefix = parseInt(parts[1])
|
||||
if ipaddr.family == IpAddressFamily.IPv4 and
|
||||
(prefix < 0 or prefix > 32):
|
||||
prefix = 32
|
||||
elif ipaddr.family == IpAddressFamily.IPv6 and
|
||||
(prefix < 0 or prefix > 128):
|
||||
prefix = 128
|
||||
result = t.init(host, prefix)
|
||||
try:
|
||||
prefix = parseInt(parts[1])
|
||||
except:
|
||||
prefix = -1
|
||||
if prefix == -1:
|
||||
ipaddr = parseIpAddress(parts[1])
|
||||
if ipaddr.family == IpAddressFamily.IPv4:
|
||||
mhost = TransportAddress(family: AddressFamily.IPv4)
|
||||
mhost.address_v4 = ipaddr.address_v4
|
||||
elif ipaddr.family == IpAddressFamily.IPv6:
|
||||
mhost = TransportAddress(family: AddressFamily.IPv6)
|
||||
mhost.address_v6 = ipaddr.address_v6
|
||||
mask = IpMask.init(mhost)
|
||||
if mask.family != host.family:
|
||||
raise newException(TransportAddressError,
|
||||
"Incorrect network address!")
|
||||
else:
|
||||
if (ipaddr.family == IpAddressFamily.IPv4 and
|
||||
(prefix <= 0 or prefix > 32)) or
|
||||
(ipaddr.family == IpAddressFamily.IPv6 and
|
||||
(prefix <= 0 or prefix > 128)):
|
||||
raise newException(TransportAddressError,
|
||||
"Incorrect network address!")
|
||||
if prefix == -1:
|
||||
result = t.init(host, mask)
|
||||
else:
|
||||
result = t.init(host, prefix)
|
||||
except:
|
||||
raise newException(TransportAddressError, "Incorrect address family!")
|
||||
raise newException(TransportAddressError, "Incorrect network address!")
|
||||
|
||||
proc `==`*(n1, n2: IpNet): bool {.inline.} =
|
||||
## Returns ``true`` if networks ``n1`` and ``n2`` are equal in IP family and
|
||||
## by value.
|
||||
if n1.host.family == n2.host.family:
|
||||
if n1.host.family == AddressFamily.IPv4:
|
||||
result = (n1.host.address_v4 == n2.host.address_v4) and
|
||||
(n1.mask == n2.mask)
|
||||
elif n1.host.family == AddressFamily.IPv6:
|
||||
result = (n1.host.address_v6 == n2.host.address_v6) and
|
||||
(n1.mask == n2.mask)
|
||||
|
||||
proc contains*(net: IpNet, address: TransportAddress): bool =
|
||||
## Returns ``true`` if ``address`` belongs to IP Network ``net``
|
||||
if net.host.family == address.family:
|
||||
var host = mask(address, net.mask)
|
||||
result = (net.host == host)
|
||||
var host1 = mask(address, net.mask)
|
||||
var host2 = mask(net.host, net.mask)
|
||||
host2.port = host1.port
|
||||
result = (host1 == host2)
|
||||
|
||||
proc broadcast*(net: IpNet): TransportAddress =
|
||||
## Returns broadcast address for IP Network ``net``.
|
||||
result = TransportAddress(family: net.host.family)
|
||||
if result.family == AddressFamily.IPv4:
|
||||
var address = cast[ptr uint32](unsafeAddr net.host.address_v4[0])[]
|
||||
var mask = cast[ptr uint32](unsafeAddr net.mask.mask4)[]
|
||||
let address = cast[ptr uint32](unsafeAddr net.host.address_v4[0])[]
|
||||
let mask = cast[ptr uint32](unsafeAddr net.mask.mask4)[]
|
||||
cast[ptr uint32](addr result.address_v4[0])[] = address or (not(mask))
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
var address0 = cast[ptr uint64](unsafeAddr net.host.address_v6[0])[]
|
||||
var address1 = cast[ptr uint64](unsafeAddr net.host.address_v6[8])[]
|
||||
var data0 = cast[ptr uint64](unsafeAddr net.mask.mask6[0])[]
|
||||
var data1 = cast[ptr uint64](unsafeAddr net.mask.mask6[1])[]
|
||||
let address0 = cast[ptr uint64](unsafeAddr net.host.address_v6[0])[]
|
||||
let address1 = cast[ptr uint64](unsafeAddr net.host.address_v6[8])[]
|
||||
let data0 = cast[ptr uint64](unsafeAddr net.mask.mask6[0])[]
|
||||
let data1 = cast[ptr uint64](unsafeAddr net.mask.mask6[1])[]
|
||||
cast[ptr uint64](addr result.address_v6[0])[] = address0 or (not(data0))
|
||||
cast[ptr uint64](addr result.address_v6[8])[] = address1 or (not(data1))
|
||||
|
||||
proc subnetMask*(net: IpNet): TransportAddress =
|
||||
## Returns netmask address for IP Network ``net``
|
||||
## Returns netmask address for IP Network ``net``.
|
||||
result = TransportAddress(family: net.host.family)
|
||||
if result.family == AddressFamily.IPv4:
|
||||
var address = cast[ptr uint32](unsafeAddr net.mask.mask4)[]
|
||||
let address = cast[ptr uint32](unsafeAddr net.mask.mask4)[]
|
||||
cast[ptr uint32](addr result.address_v4[0])[] = address
|
||||
elif result.family == AddressFamily.IPv6:
|
||||
var address0 = cast[ptr uint64](unsafeAddr net.mask.mask6[0])[]
|
||||
var address1 = cast[ptr uint64](unsafeAddr net.mask.mask6[1])[]
|
||||
let address0 = cast[ptr uint64](unsafeAddr net.mask.mask6[0])[]
|
||||
let address1 = cast[ptr uint64](unsafeAddr net.mask.mask6[1])[]
|
||||
cast[ptr uint64](addr result.address_v6[0])[] = address0
|
||||
cast[ptr uint64](addr result.address_v6[8])[] = address1
|
||||
|
||||
proc network*(net: IpNet): TransportAddress {.inline.} =
|
||||
## Returns network address (host address masked with network mask) for
|
||||
## IP Network ``net``.
|
||||
result = mask(net.host, net.mask)
|
||||
|
||||
proc `and`*(address1, address2: TransportAddress): TransportAddress =
|
||||
## Bitwise ``and`` operation for ``address1 and address2``.
|
||||
##
|
||||
|
@ -430,13 +564,21 @@ proc `$`*(net: IpNet): string =
|
|||
address_v4: net.host.address_v4)
|
||||
result = $a
|
||||
result.add("/")
|
||||
result.add($net.mask.prefix())
|
||||
let prefix = net.mask.prefix()
|
||||
if prefix == -1:
|
||||
result.add(net.mask.ip())
|
||||
else:
|
||||
result.add($prefix)
|
||||
elif net.host.family == AddressFamily.IPv6:
|
||||
var a = IpAddress(family: IpAddressFamily.IPv6,
|
||||
address_v6: net.host.address_v6)
|
||||
result = $a
|
||||
result.add("/")
|
||||
result.add($net.mask.prefix())
|
||||
let prefix = net.mask.prefix()
|
||||
if prefix == -1:
|
||||
result.add(net.mask.ip())
|
||||
else:
|
||||
result.add($prefix)
|
||||
|
||||
proc isUnspecified*(address: TransportAddress): bool {.inline.} =
|
||||
## Returns ``true`` if ``address`` is not specified yet, e.g. its ``family``
|
||||
|
@ -555,34 +697,3 @@ proc isGlobalMulticast*(address: TransportAddress): bool =
|
|||
elif address.family == AddressFamily.IPv6:
|
||||
result = (address.address_v6[0] == 0xFF'u8) and
|
||||
((address.address_v6[1] and 0x0F'u8) == 0x0E'u8)
|
||||
|
||||
when isMainModule:
|
||||
var MaskVectors = [
|
||||
["192.168.1.127:1024", "255.255.255.128", "192.168.1.0:1024"],
|
||||
["192.168.1.127:1024", "255.255.255.192", "192.168.1.64:1024"],
|
||||
["192.168.1.127:1024", "255.255.255.224", "192.168.1.96:1024"],
|
||||
["192.168.1.127:1024", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80",
|
||||
"192.168.1.0:1024"],
|
||||
["192.168.1.127:1024", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0",
|
||||
"192.168.1.64:1024"],
|
||||
["192.168.1.127:1024", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0",
|
||||
"192.168.1.96:1024"],
|
||||
["192.168.1.127:1024", "255.0.255.0", "192.0.1.0:1024"],
|
||||
["[2001:db8::1]:1024", "ffff:ff80::", "[2001:d80::]:1024"],
|
||||
["[2001:db8::1]:1024", "f0f0:0f0f::", "[2000:d08::]:1024"]
|
||||
]
|
||||
for item in MaskVectors:
|
||||
var a = initTAddress(item[0])
|
||||
var m = IpMask.init(item[1])
|
||||
var r = a.mask(m)
|
||||
echo r
|
||||
# var temp = [0'u8, 0, 255, 255, 255, 255, 255, 0]
|
||||
# echo toHex(cast[ptr uint64](addr temp[0])[])
|
||||
# # {IPv4(192, 168, 1, 127), IPMask(ParseIP("255.255.255.192")), IPv4(192, 168, 1, 64)},
|
||||
# echo initTAddress("255.255.255.128", 0).toIPv6()
|
||||
# var a = initTAddress("255.255.255.0", 0).toIPv6()
|
||||
# echo a
|
||||
# var m = IpMask.init(a)
|
||||
# var b = initTAddress("192.168.1.127", 0)
|
||||
# echo b.mask(m)
|
||||
# # echo a.mask(m)
|
Loading…
Reference in New Issue