punchd/network_interface.nim

47 lines
1.8 KiB
Nim
Raw Normal View History

2020-05-21 01:17:37 +02:00
from nativesockets import getAddrString
from posix import SockAddr, Sockaddr_in, inet_ntoa, AF_INET
type
NetworkInterface* = object
ipAddress*: string
name*: string
index*: cint
flags*: cuint
NetworkInterfaceError* = object of ValueError
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".}
proc fromIpAddress*(address: string): NetworkInterface =
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
it.ifa_addr.sa_family.cint == AF_INET and
it.ifa_addr.getAddrString() == address:
result.ipAddress = address
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")