Uses the SIOCGIFCONF ioctl to obtain a list of interfaces and extracts those names, returning them in a list of strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import socket
import fcntl
import struct
import array
def all_interfaces():
max_possible = 128 # arbitrary. raise if needed.
bytes = max_possible * 32
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
names = array.array('B', '\0' * bytes)
outbytes = struct.unpack('iL', fcntl.ioctl(
s.fileno(),
0x8912, # SIOCGIFCONF
struct.pack('iL', bytes, names.buffer_info()[0])
))[0]
namestr = names.tostring()
return [namestr[i:i+32].split('\0', 1)[0] for i in range(0, outbytes, 32)]
|
This solution should be faster than running ifconfig and parsing its output, and simpler than reading and parsing /proc/net/dev, since that will list all existing interfaces, whether active (up) or not.
This solution probably only works on Linux-- and possibly not all versions of even that-- since it depends on some C structures having a particular size and layout, as well as having the SIOCGIFCONF ioctl number (0x8912) hardcoded. I believe it could be adjusted, though, to work on other Unix systems.
struct ifconf has changed... I wish we didn't have to use constants for the structure offsets... For a 2.6.17 kernel the above offsets are incorrect. I've replaced the last line with:
The above is for a 64 bit kernel... Ah, structure offsets have not changed over the years for 32 bit kernels, my patch is for a 64 bit 2.6.17 kernel.
no need for format_ip. You could have done: socket.inet_ntoa(ip)
To go along with Duane Voth's comment, here's a little extra to detect whether the code is running on 64bit or 32bit and then run the platform-specific code. It also returns a list of tuples of (iface, iface_ip), in case anyone needs the IP addresses associated with those interfaces.
I know, my code's not particularly pretty, but it seems to work on both 32bit and 64bit systems.
I most specifically apologize for the naming of var1 and var2 - I honestly don't know what they represent, or I would probably have come up with a different naming convention for them. If anyone can clue me in, I am actually curious (but have had a hard time googling for the types of things done in this code).
i can't understand how the data are passed in the array...could you help me understand it a bit more...and second question how do u know where to check for ip?i mean why is it in [20:24] where did you find those info?
I tried this script on a ubuntu machine - all packages are up to date. However, the localifs() function returns all setup interfaces. Meaning, if the interface has an invalid static ip address it will be returned as an 'up' interface, although it is not. I wrote a script in /etc/network/if-up.d/mystartupscript, which writes a log that a new interface has come up. This script does not run for an invalid interface configuration.
Is there a way, that invalid configured interfaces, which are not 'up', are not included in the result set?
Thanks to all previous comments combined, here's a version that works on both 32- and 64-bits, returns both the interface name and its address, and as a bonus isn't limited to 128 interfaces (although I don't believe it's really going to be a problem for anyone)
Many thanks to Noam Yorav-Raphael. I've adapted his code to work in python 3.4: