2020-05-21 01:17:37 +02:00
|
|
|
from nativesockets import getAddrString
|
2020-07-22 01:28:55 +02:00
|
|
|
from net import IpAddress, parseIpAddress, `$`
|
|
|
|
from posix import SockAddr, AF_INET, AF_INET6
|
2020-05-21 01:17:37 +02:00
|
|
|
|
|
|
|
type
|
|
|
|
NetworkInterface* = object
|
2020-07-22 01:28:55 +02:00
|
|
|
ipAddress*: IpAddress
|
|
|
|
netMask*: IpAddress
|
2020-05-21 01:17:37 +02:00
|
|
|
name*: string
|
|
|
|
index*: cint
|
|
|
|
flags*: cuint
|
|
|
|
|
2020-07-07 19:37:40 +02:00
|
|
|
NetworkInterfaceError* = object of CatchableError
|
2020-05-21 01:17:37 +02:00
|
|
|
|
|
|
|
Ifaddrs {.importc: "struct ifaddrs", pure, final,
|
|
|
|
header: "<ifaddrs.h>".} = object
|
|
|
|
ifa_next: ptr Ifaddrs # Next item in list
|
|
|
|
ifa_name: cstring # Name of interface
|
|
|
|
ifa_flags: cuint # Flags from SIOCGIFFLAGS
|
|
|
|
ifa_addr: ptr SockAddr # Address of interface
|
|
|
|
ifa_netmask: ptr SockAddr # Netmask of interface
|
|
|
|
ifa_ifu: ptr SockAddr # Broadcast / point-to-point address (we don't care about the union)
|
|
|
|
ifa_data: pointer # Address-specific data
|
|
|
|
|
|
|
|
proc getifaddrs(ifap: ptr ptr Ifaddrs): int {.header: "<ifaddrs.h>", importc: "getifaddrs".}
|
|
|
|
proc freeifaddrs(ifap: ptr Ifaddrs): void {.header: "<ifaddrs.h>", importc: "freeifaddrs".}
|
|
|
|
proc if_nametoindex(ifname: cstring): cuint {.header: "<net/if.h>", importc: "if_nametoindex".}
|
|
|
|
|
2020-07-22 01:28:55 +02:00
|
|
|
proc fromIpAddress*(address: IpAddress): NetworkInterface =
|
2020-05-21 01:17:37 +02:00
|
|
|
var interfaces: ptr Ifaddrs
|
|
|
|
if getifaddrs(addr interfaces) != 0:
|
|
|
|
raise newException(NetworkInterfaceError, "getifaddrs failed")
|
|
|
|
var it = interfaces
|
|
|
|
while it != nil:
|
|
|
|
if it.ifa_addr != nil and
|
2020-07-22 01:28:55 +02:00
|
|
|
(it.ifa_addr.sa_family.cint == AF_INET or
|
|
|
|
it.ifa_addr.sa_family.cint == AF_INET6) and
|
|
|
|
$address == it.ifa_addr.getAddrString():
|
2020-05-21 01:17:37 +02:00
|
|
|
result.ipAddress = address
|
2020-07-25 12:00:21 +02:00
|
|
|
result.netMask = parseIpAddress(it.ifa_netmask.getAddrString())
|
2020-05-21 01:17:37 +02:00
|
|
|
result.name = $it.ifa_name
|
|
|
|
result.index = if_nametoindex(result.name).cint
|
|
|
|
result.flags = it.ifa_flags
|
|
|
|
break
|
|
|
|
it = it.ifa_next
|
|
|
|
freeifaddrs(interfaces)
|
|
|
|
if result.name == "":
|
|
|
|
raise newException(NetworkInterfaceError, "interface for given IP address not found")
|
|
|
|
if result.index <= 0:
|
|
|
|
raise newException(NetworkInterfaceError, "cannot get interface index")
|