Reputation: 5263
How would one go about retrieving a network device's netmask (In Linux preferably, but if it's cross-platform then cool)? I know how in C on Linux but I can't find a way in Python -- minus ctypes perhaps. That or parsing ifconfig. Any other way?
ioctl(socknr, SIOCGIFNETMASK, &ifreq) // C version
Upvotes: 7
Views: 23959
Reputation: 4659
Answer using psutil:
import psutil
import socket
def get_ipv4_netmask_from_nic(interface):
interface_addrs = psutil.net_if_addrs().get(interface) or []
for snicaddr in interface_addrs:
if snicaddr.family == socket.AF_INET:
return snicaddr.netmask
Example:
>>> get_ipv4_netmask_from_nic("eth0")
'255.255.255.0'
Upvotes: 2
Reputation: 1
I have an update on the original answer as the original code:
struct.pack('256s', iface)
Throws an error in Python 3.9, so here is a revisited version:
SIOCGIFADDR = 0x8915
def get_iface_ip(iface: str):
"""
Get network interface IP using the network interface name
:param iface: Interface name (like eth0, enp2s0, etc.)
:return IP address in the form XX.XX.XX.XX
"""
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
iface_bin = struct.pack('256s', bytes(iface, 'utf-8'))
packet_ip = fcntl.ioctl(s.fileno(), SIOCGIFADDR, iface_bin)[20:24]
return socket.inet_ntoa(packet_ip)
Upvotes: 0
Reputation: 951
In Windows this piece of code may be useful:
import os
import sys
import _winreg
def main():
adapter_list_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards')
adapter_count = _winreg.QueryInfoKey(adapter_list_key)[0]
for i in xrange(adapter_count):
sub_key_name = _winreg.EnumKey(adapter_list_key, i)
adapter_key = _winreg.OpenKey(adapter_list_key, sub_key_name)
(adapter_service_name, _) = _winreg.QueryValueEx(adapter_key, "ServiceName")
(description, _) = _winreg.QueryValueEx(adapter_key, "Description")
adapter_registry_path = os.path.join(r'SYSTEM\ControlSet001\Services',
adapter_service_name, "Parameters", "Tcpip")
adapter_service_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
adapter_registry_path)
(subnet_mask, _) = _winreg.QueryValueEx(adapter_service_key, "SubnetMask")
(ip_address, _) = _winreg.QueryValueEx(adapter_service_key, "IpAddress")
sys.stdout.write("Name: %s\n" % adapter_service_name)
sys.stdout.write("Description: %s\n" % description)
sys.stdout.write("SubnetMask: %s\n" % subnet_mask)
sys.stdout.write("IpAdress: %s\n" % ip_address)
if __name__ == "__main__":
main()
Get network adapters list from HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
registry key and than extract more info about each adapter from HKLM\SYSTEM\ControlSet001\Services\{adapter_guid}\Parameters\Tcpip
key.
I test it on Windows XP with 2 virtual adapters, it works fine. Should work in 2000, 2003, and Vista too.
Upvotes: 1
Reputation: 121
The netifaces
module deserves a mention here. Straight from the docs:
>>> netifaces.interfaces()
['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0']
>>> addrs = netifaces.ifaddresses('en0')
>>> addrs[netifaces.AF_INET]
[{'broadcast': '10.15.255.255', 'netmask': '255.240.0.0', 'addr': '10.0.1.4'}, {'broadcast': '192.168.0.255', 'addr': '192.168.0.47'}]
Works on Windows, Linux, OS X, and probably other UNIXes.
Upvotes: 9
Reputation: 919
Using the python pyroute2 library you can get all network element attributes:
from pyroute2 import IPRoute
ip = IPRoute()
info = [{'iface': x['index'], 'addr': x.get_attr('IFA_ADDRESS'), 'mask': x['prefixlen']} for x in ip.get_addr()]
More information available here:http://pyroute2.org/pyroute2-0.3.14p4/iproute.html
Upvotes: 0
Reputation: 839
I had the idea to rely on subprocess to use a simple ifconfig (Linux) or ipconfig (windows) request to retrieve the info (if the ip is known). Comments welcome :
WINDOWS
ip = '192.168.1.10' #Example
proc = subprocess.Popen('ipconfig',stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline()
if ip.encode() in line:
break
mask = proc.stdout.readline().rstrip().split(b':')[-1].replace(b' ',b'').decode()
UNIX-Like
ip = '192.168.1.10' #Example
proc = subprocess.Popen('ifconfig',stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline()
if ip.encode() in line:
break
mask = line.rstrip().split(b':')[-1].replace(b' ',b'').decode()
IP is retrieved using a socket connection to the web and using getsockname()[0]
Upvotes: 3
Reputation: 21
You can use this library: http://github.com/rlisagor/pynetlinux. Note: I'm the author of the library.
Upvotes: 2
Reputation: 340151
Did you look here?
http://docs.python.org/library/fcntl.html
This works for me in python 2.5.2 on Linux. Was finishing it when Ben got ahead, but still here it goes (sad to waste the effort :-) ):
vinko@parrot:~$ more get_netmask.py
# get_netmask.py by Vinko Vrsalovic 2009
# Inspired by http://code.activestate.com/recipes/439093/
# and http://code.activestate.com/recipes/439094/
# Code: 0x891b SIOCGIFNETMASK
import socket
import fcntl
import struct
import sys
def get_netmask(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x891b, struct.pack('256
s',ifname))[20:24])
if len(sys.argv) == 2:
print get_netmask(sys.argv[1])
vinko@parrot:~$ python get_netmask.py lo
255.0.0.0
vinko@parrot:~$ python get_netmask.py eth0
255.255.255.0
Upvotes: 4