Commit d2d799f1 authored by Julien Muchembled's avatar Julien Muchembled

Better support of default route

parent 2477ff52
......@@ -186,7 +186,7 @@ if 1:
p.communicate(str(token[0]))
os.remove(dh_path)
os.remove(folder + '/ca.crt')
node.screen('../re6stnet @%s/re6stnet.conf -v%u --registry %s %s'
node.screen('../re6stnet @%s/re6stnet.conf --table 0 -v%u --registry %s %s'
% (folder, VERBOSE, registry, args))
re6stnet(registry, 'registry', '--ip ' + REGISTRY, registry='http://localhost/')
re6stnet(machine1, 'm1', '-I%s' % m1_if_0.name)
......
......@@ -52,7 +52,7 @@ def client(iface, server_address, encrypt, *args, **kw):
return openvpn(iface, encrypt, *remote, **kw)
def router(subnet, hello_interval, gateway, log_path, state_path, pidfile,
def router(subnet, hello_interval, table, log_path, state_path, pidfile,
tunnel_interfaces, *args, **kw):
s = utils.ipFromBin(subnet)
n = len(subnet)
......@@ -66,7 +66,12 @@ def router(subnet, hello_interval, gateway, log_path, state_path, pidfile,
'-C', 'redistribute local deny',
'-C', 'redistribute ip %s/%u eq %u' % (s, n, n),
'-C', 'redistribute deny']
if gateway:
if table:
cmd += '-t%u' % table, '-T%u' % table
elif table is None:
# Tell peers not to route external IP via me.
cmd += '-C', 'out eq 0 deny'
else:
cmd[-2:-2] = '-C', 'redistribute ip ::/0 eq 0'
for iface in tunnel_interfaces:
cmd += '-C', 'interface %s rxcost 512' % iface
......
......@@ -50,6 +50,9 @@ def getConfig():
" hello interval. It takes between 3 and 4 times the"
" hello interval for Babel to re-establish connection with a"
" node for which the direct connection has been cut.")
_('--table', type=int, default=42,
help="Use given table id. If 0, the main table will be used and any"
" existing default route will be exported.")
_ = parser.add_argument_group('tunnelling').add_argument
_('-O', dest='openvpn_args', metavar='ARG', action='append', default=[],
......@@ -148,15 +151,22 @@ def main():
for x in pp:
server_tunnels.setdefault('re6stnet-' + x[1], x)
def call(cmd):
logging.debug('%r', cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode:
raise EnvironmentError("%r failed with error %u\n%s"
% (' '.join(cmd), p.returncode, stderr))
return stdout
def required(arg):
if not getattr(config, arg):
sys.exit("error: argument --%s is required" % arg)
def ip(object, *args):
args = ['ip', object, 'add'] + list(args)
r = subprocess.call(args)
if r:
sys.exit(r)
args[2] = 'del'
args = ['ip', '-6', object, 'add'] + list(args)
call(args)
args[3] = 'del'
cleanup.append(lambda: subprocess.call(args))
try:
......@@ -180,16 +190,9 @@ def main():
else:
tunnel_manager = write_pipe = None
config.babel_args += config.iface_list
cleanup = [plib.router(subnet, config.hello, tunnel_manager is not None,
os.path.join(config.log, 'babeld.log'),
os.path.join(config.state, 'babeld.state'),
config.babel_pidfile, tunnel_interfaces,
*config.babel_args).terminate]
cleanup = []
try:
my_network = "%s/%u" % (utils.ipFromBin(network), len(network))
ip('route', 'unreachable', my_network, 'proto', 'static')
# Source address selection is defined by RFC 3484, and in most
# applications, it usually works thanks to rule 5 (prefer outgoing
# interface). But here, it rarely applies because we use several
......@@ -217,14 +220,44 @@ def main():
'--ping-exit', str(timeout), *config.openvpn_args).kill)
ip('addr', my_ip, 'dev', config.main_interface)
if_rt = ['ip', '-6', 'route', 'del',
'fe80::/64', 'dev', config.main_interface]
if config.main_interface == 'lo':
# WKRD: The kernel does not remove these routes on exit.
# The first one can be removed now.
del_rtr = ['ip', 'route', 'del', 'unreachable', 'fe80::/64',
'dev', 'lo']
subprocess.call(del_rtr)
del_rtr[4] = '%s/%u' % (utils.ipFromBin(subnet), len(subnet))
cleanup.append(lambda: subprocess.call(del_rtr))
# WKRD: Removed this useless route now, since the kernel does
# not even remove it on exit.
subprocess.call(if_rt)
if_rt[4] = '%s/%u' % (utils.ipFromBin(subnet), len(subnet))
cleanup.append(lambda: subprocess.call(if_rt))
x = [my_network]
if config.table:
x += 'table', str(config.table)
try:
ip('rule', 'from', *x)
except EnvironmentError:
logging.warning("I refuse to forward packets whose"
" destination IP is not part of %s, because your kernel"
" was compiled without support for source-based routing"
" policy. Pass --table 0 if you are sure you don't"
" have any default route.", my_network)
# XXX: The issue with such fallback is that a node will be
# unreachable from outside if it is only connected to
# limited peers. This could be fixed the same way as
# for checking connectedness.
config.table = None
del x[1:]
else:
ip('rule', 'to', *x)
call(if_rt)
if_rt += x[1:]
call(if_rt[:3] + ['add', 'proto', 'static'] + if_rt[4:])
ip('route', 'unreachable', *x)
config.babel_args += config.iface_list
cleanup.append(plib.router(subnet, config.hello, config.table,
os.path.join(config.log, 'babeld.log'),
os.path.join(config.state, 'babeld.state'),
config.babel_pidfile, tunnel_interfaces,
*config.babel_args).terminate)
if config.up:
r = os.system(config.up)
if r:
......@@ -255,9 +288,9 @@ def main():
if forwarder and t >= forwarder.next_refresh:
forwarder.refresh()
finally:
for cleanup in cleanup:
while cleanup:
try:
cleanup()
cleanup.pop()()
except:
pass
except sqlite3.Error:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment