Skip to content

Instantly share code, notes, and snippets.

@pyther
Last active January 28, 2021 07:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pyther/188be6c60f180fbc98fa2e22799ef3bc to your computer and use it in GitHub Desktop.
Save pyther/188be6c60f180fbc98fa2e22799ef3bc to your computer and use it in GitHub Desktop.
Listens for networkd signals and deprecate the ip6 route on the interface when the interface gets reconfigured
#!/usr/bin/env python3
from functools import cache
import argparse
import dbus
import subprocess
import json
import dbus.mainloop.glib
from gi.repository import GLib as glib
IFACE = None
PREFIX = None
def ip_addr_show(dev):
cmd = ['ip', '-j', '-6', 'addr', 'show', 'dev', dev]
p = subprocess.run(cmd, capture_output=True, check=True)
stdout = p.stdout.decode('utf-8')
return json.loads(stdout)
def deprecate_address(dev, prefix):
addrs = [x for x in ip_addr_show(dev)[0]['addr_info']
if x['local'].startswith(prefix)]
if not len(addrs):
print(f"address matching {prefix} on {dev} not found")
return
# Deprecate all matching Addresses
for addr in addrs:
if addr['preferred_life_time'] == 0:
return
local = str(addr['local'])
valid = str(addr['valid_life_time'])
cmd = ['ip', 'addr', 'change', local, 'dev', dev, 'valid_lft', valid, 'preferred_lft', '0']
subprocess.run(cmd, capture_output=True, check=True)
print(f"{dev}: deprecated {local} valid_lft {valid} preferred_lft 0")
return
@cache
def get_ifindex(dev):
with open(f"/sys/class/net/{dev}/ifindex") as fd:
idx = fd.readline().strip()
return idx
def property_changed(typ, data, _, path):
if typ != 'org.freedesktop.network1.Link':
return
if not path.startswith('/org/freedesktop/network1/link/_'):
return
idx = path.replace('/org/freedesktop/network1/link/_', '').split('/')[0]
idx = chr(int(idx[:2], 16))
try:
ifindex = get_ifindex(IFACE)
except IOError:
return
# Ignore changes for interfaces we don't care about
if idx != ifindex:
return
# When address lifetime is refreshed, the AdministrativeState property
# changes to 'configuring', then transitions to 'configured'
if data.get('AdministrativeState') != 'configured':
return
deprecate_address(IFACE, PREFIX)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='deprecate ip6 address')
parser.add_argument('-i', '--interface', required=True,
help='interface to deprecate address on')
parser.add_argument('-p', '--prefix', default='2001:506',
help='address prefix to match against')
args = parser.parse_args()
IFACE = args.interface
PREFIX = args.prefix
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
bus.add_signal_receiver(property_changed,
bus_name='org.freedesktop.network1',
signal_name='PropertiesChanged',
path_keyword='path')
print("Monitoring org.freedesktop.network1")
mainloop = glib.MainLoop()
mainloop.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment