Python: get default gateway for a local interface/ip address in linux
Question:
On Linux, how can I find the default gateway for a local ip address/interface using python?
I saw the question “How to get internal IP, external IP and default gateway for UPnP”, but the accepted solution only shows how to get the local IP address for a network interface on windows.
Thanks.
Answers:
It seems http://pypi.python.org/pypi/pynetinfo/0.1.9 can do this, but I haven’t tested it.
def get_ip():
file=os.popen("ifconfig | grep 'addr:'")
data=file.read()
file.close()
bits=data.strip().split('n')
addresses=[]
for bit in bits:
if bit.strip().startswith("inet "):
other_bits=bit.replace(':', ' ').strip().split(' ')
for obit in other_bits:
if (obit.count('.')==3):
if not obit.startswith("127."):
addresses.append(obit)
break
return addresses
For those people who don’t want an extra dependency and don’t like calling subprocesses, here’s how you do it yourself by reading /proc/net/route
directly:
import socket, struct
def get_default_gateway_linux():
"""Read the default gateway directly from /proc."""
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
# If not default route or not RTF_GATEWAY, skip it
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
I don’t have a big-endian machine to test on, so I’m not sure whether the endianness is dependent on your processor architecture, but if it is, replace the <
in struct.pack('<L', ...
with =
so the code will use the machine’s native endianness.
The latest version of netifaces
can do this too, but unlike pynetinfo
, it will work on systems other than Linux (including Windows, OS X, FreeBSD and Solaris).
For completeness (and to expand on alastair’s answer), here is an example that uses “netifaces” (tested under Ubuntu 10.04, but this should be portable):
$ sudo easy_install netifaces
Python 2.6.5 (r265:79063, Oct 1 2012, 22:04:36)
...
$ ipython
...
In [8]: import netifaces
In [9]: gws=netifaces.gateways()
In [10]: gws
Out[10]:
{2: [('192.168.0.254', 'eth0', True)],
'default': {2: ('192.168.0.254', 'eth0')}}
In [11]: gws['default'][netifaces.AF_INET][0]
Out[11]: '192.168.0.254'
Documentation for ‘netifaces’: https://pypi.python.org/pypi/netifaces/
You can get it like this (Tested with python 2.7 and Mac OS X Capitain but should work on GNU/Linux too):
import subprocess
def system_call(command):
p = subprocess.Popen([command], stdout=subprocess.PIPE, shell=True)
return p.stdout.read()
def get_gateway_address():
return system_call("route -n get default | grep 'gateway' | awk '{print $2}'")
print get_gateway_address()
here my solution to get default gateway for Mac and Linux with python:
import subprocess
import re
import platform
def get_default_gateway_and_interface():
if platform.system() == "Darwin":
route_default_result = subprocess.check_output(["route", "get", "default"])
gateway = re.search(r"d{1,3}.d{1,3}.d{1,3}.d{1,3}", route_default_result).group(0)
default_interface = re.search(r"(?:interface:.)(.*)", route_default_result).group(1)
elif platform.system() == "Linux":
route_default_result = re.findall(r"([w.][w.]*'?w?)", subprocess.check_output(["ip", "route"]))
gateway = route_default_result[2]
default_interface = route_default_result[4]
if route_default_result:
return(gateway, default_interface)
else:
print("(x) Could not read default routes.")
gateway, default_interface = get_default_gateway_and_interface()
print(gateway)
for Mac:
import subprocess
def get_default_gateway():
route_default_result = str(subprocess.check_output(["route", "get", "default"]))
start = 'gateway: '
end = '\n'
if 'gateway' in route_default_result:
return (route_default_result.split(start))[1].split(end)[0]
print(get_default_gateway())
Here a solution if you have multiple default gateways.
import socket, struct
from pprint import pprint as pp
with open("/proc/net/route") as fh:
# skip header
next(fh)
route_list = []
for line in fh:
routes = line.strip().split()
destination = socket.inet_ntoa(struct.pack("<L", int(routes[1], 16)))
if destination != "0.0.0.0":
continue
gateway = socket.inet_ntoa(struct.pack("<L", int(routes[2], 16)))
mask = socket.inet_ntoa(struct.pack("<L", int(routes[7], 16)))
metric = routes[6]
interface = routes[0]
route_table = (destination, gateway, mask, metric, interface)
route_list.append(route_table)
pp(route_list)
#[('0.0.0.0', '0.0.0.0', '0.0.0.0', '0', 'wlan0'),
# ('0.0.0.0', '192.168.225.1', '0.0.0.0', '1024', 'usb0')]
On Linux, how can I find the default gateway for a local ip address/interface using python?
I saw the question “How to get internal IP, external IP and default gateway for UPnP”, but the accepted solution only shows how to get the local IP address for a network interface on windows.
Thanks.
It seems http://pypi.python.org/pypi/pynetinfo/0.1.9 can do this, but I haven’t tested it.
def get_ip():
file=os.popen("ifconfig | grep 'addr:'")
data=file.read()
file.close()
bits=data.strip().split('n')
addresses=[]
for bit in bits:
if bit.strip().startswith("inet "):
other_bits=bit.replace(':', ' ').strip().split(' ')
for obit in other_bits:
if (obit.count('.')==3):
if not obit.startswith("127."):
addresses.append(obit)
break
return addresses
For those people who don’t want an extra dependency and don’t like calling subprocesses, here’s how you do it yourself by reading /proc/net/route
directly:
import socket, struct
def get_default_gateway_linux():
"""Read the default gateway directly from /proc."""
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
# If not default route or not RTF_GATEWAY, skip it
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
I don’t have a big-endian machine to test on, so I’m not sure whether the endianness is dependent on your processor architecture, but if it is, replace the <
in struct.pack('<L', ...
with =
so the code will use the machine’s native endianness.
The latest version of netifaces
can do this too, but unlike pynetinfo
, it will work on systems other than Linux (including Windows, OS X, FreeBSD and Solaris).
For completeness (and to expand on alastair’s answer), here is an example that uses “netifaces” (tested under Ubuntu 10.04, but this should be portable):
$ sudo easy_install netifaces
Python 2.6.5 (r265:79063, Oct 1 2012, 22:04:36)
...
$ ipython
...
In [8]: import netifaces
In [9]: gws=netifaces.gateways()
In [10]: gws
Out[10]:
{2: [('192.168.0.254', 'eth0', True)],
'default': {2: ('192.168.0.254', 'eth0')}}
In [11]: gws['default'][netifaces.AF_INET][0]
Out[11]: '192.168.0.254'
Documentation for ‘netifaces’: https://pypi.python.org/pypi/netifaces/
You can get it like this (Tested with python 2.7 and Mac OS X Capitain but should work on GNU/Linux too):
import subprocess
def system_call(command):
p = subprocess.Popen([command], stdout=subprocess.PIPE, shell=True)
return p.stdout.read()
def get_gateway_address():
return system_call("route -n get default | grep 'gateway' | awk '{print $2}'")
print get_gateway_address()
here my solution to get default gateway for Mac and Linux with python:
import subprocess
import re
import platform
def get_default_gateway_and_interface():
if platform.system() == "Darwin":
route_default_result = subprocess.check_output(["route", "get", "default"])
gateway = re.search(r"d{1,3}.d{1,3}.d{1,3}.d{1,3}", route_default_result).group(0)
default_interface = re.search(r"(?:interface:.)(.*)", route_default_result).group(1)
elif platform.system() == "Linux":
route_default_result = re.findall(r"([w.][w.]*'?w?)", subprocess.check_output(["ip", "route"]))
gateway = route_default_result[2]
default_interface = route_default_result[4]
if route_default_result:
return(gateway, default_interface)
else:
print("(x) Could not read default routes.")
gateway, default_interface = get_default_gateway_and_interface()
print(gateway)
for Mac:
import subprocess
def get_default_gateway():
route_default_result = str(subprocess.check_output(["route", "get", "default"]))
start = 'gateway: '
end = '\n'
if 'gateway' in route_default_result:
return (route_default_result.split(start))[1].split(end)[0]
print(get_default_gateway())
Here a solution if you have multiple default gateways.
import socket, struct
from pprint import pprint as pp
with open("/proc/net/route") as fh:
# skip header
next(fh)
route_list = []
for line in fh:
routes = line.strip().split()
destination = socket.inet_ntoa(struct.pack("<L", int(routes[1], 16)))
if destination != "0.0.0.0":
continue
gateway = socket.inet_ntoa(struct.pack("<L", int(routes[2], 16)))
mask = socket.inet_ntoa(struct.pack("<L", int(routes[7], 16)))
metric = routes[6]
interface = routes[0]
route_table = (destination, gateway, mask, metric, interface)
route_list.append(route_table)
pp(route_list)
#[('0.0.0.0', '0.0.0.0', '0.0.0.0', '0', 'wlan0'),
# ('0.0.0.0', '192.168.225.1', '0.0.0.0', '1024', 'usb0')]