Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
re6stnet
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Yohann D'Anello
re6stnet
Commits
abf8211e
Commit
abf8211e
authored
Apr 09, 2015
by
Alain Takoudjou
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'proto' into re6st-slapos
parents
47d1bb85
40d4e496
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
232 additions
and
104 deletions
+232
-104
debian/control
debian/control
+1
-1
demo/demo
demo/demo
+50
-26
demo/fixnemu.py
demo/fixnemu.py
+55
-0
demo/m1/re6stnet.conf
demo/m1/re6stnet.conf
+1
-1
demo/m2/re6stnet.conf
demo/m2/re6stnet.conf
+1
-1
demo/m3/re6stnet.conf
demo/m3/re6stnet.conf
+0
-1
demo/m4/re6stnet.conf
demo/m4/re6stnet.conf
+1
-1
demo/m5/re6stnet.conf
demo/m5/re6stnet.conf
+1
-1
demo/m6/re6stnet.conf
demo/m6/re6stnet.conf
+1
-1
demo/m7/re6stnet.conf
demo/m7/re6stnet.conf
+1
-1
demo/m8/re6stnet.conf
demo/m8/re6stnet.conf
+1
-1
demo/registry/re6st-registry.conf
demo/registry/re6st-registry.conf
+1
-0
docs/re6stnet.rst
docs/re6stnet.rst
+2
-2
re6st-registry
re6st-registry
+12
-0
re6st/cache.py
re6st/cache.py
+11
-3
re6st/ctl.py
re6st/ctl.py
+2
-0
re6st/plib.py
re6st/plib.py
+16
-12
re6st/registry.py
re6st/registry.py
+6
-2
re6st/tunnel.py
re6st/tunnel.py
+2
-1
re6stnet
re6stnet
+66
-48
re6stnet.spec
re6stnet.spec
+1
-1
No files found.
debian/control
View file @
abf8211e
...
...
@@ -7,7 +7,7 @@ Standards-Version: 3.9.1
Package: re6stnet
Architecture: all
Depends: ${misc:Depends}, python (>= 2.6.6-3), python (<< 2.8), python-argparse, python-openssl (>= 0.13), openvpn (>= 2.1.3), babeld (= 1.
5.1-nxd2
), iproute2 | iproute, openssl
Depends: ${misc:Depends}, python (>= 2.6.6-3), python (<< 2.8), python-argparse, python-openssl (>= 0.13), openvpn (>= 2.1.3), babeld (= 1.
6.0~1.g8950d3b-nxd1
), iproute2 | iproute, openssl
Recommends: ${python:Recommends}, logrotate
Suggests: ndisc6
Description: resilient, scalable, IPv6 network application
demo/demo
View file @
abf8211e
#!/usr/bin/python
import math, nemu, os, signal, socket, subprocess, sys, time, weakref
import math, nemu, os,
re,
signal, socket, subprocess, sys, time, weakref
from collections import defaultdict
IPTABLES = 'iptables'
SCREEN = 'screen'
...
...
@@ -38,6 +38,8 @@ def _add_interface(node, iface):
return Node__add_interface(node, iface)
nemu.Node._add_interface = _add_interface
execfile("fixnemu.py")
# create nodes
for name in """internet=I registry=R
gateway1=g1 machine1=1 machine2=2
...
...
@@ -48,6 +50,8 @@ for name in """internet=I registry=R
globals()[name] = node = nemu.Node()
node.name = name
node.short = short
node.Popen(('sysctl', '-q',
'net.ipv4.icmp_echo_ignore_broadcasts=0')).wait()
node._screen = node.Popen((SCREEN, '-DmS', name))
node.screen = (lambda name: lambda *cmd:
subprocess.call([SCREEN, '-r', name, '-X', 'eval'] + map(
...
...
@@ -235,7 +239,12 @@ def node_by_ll(addr):
for a in a:
p = a['prefix_len']
a = a['address']
if a.startswith('2001:db8:'):
if a.startswith('10.'):
if a.startswith('10.42.'):
assert not p % 8
_ll[socket.inet_ntoa(socket.inet_aton(
a)[:p/8].ljust(4, '\0'))] = n, t
elif a.startswith('2001:db8:'):
assert not p % 8
a = socket.inet_ntop(socket.AF_INET6,
socket.inet_pton(socket.AF_INET6,
...
...
@@ -245,17 +254,19 @@ def node_by_ll(addr):
_ll[a] = n, t
return _ll[addr]
def route_svg(
z=4
):
def route_svg(
ipv4, z = 4, default = type('', (), {'short': None})
):
graph = {}
for n in nodes:
g = graph[n] = defaultdict(list)
for r in n.get_routes():
if r.prefix and r.prefix.startswith('2001:db8:'):
if (r.prefix and r.prefix.startswith('10.42.') if ipv4 else
r.prefix is None or r.prefix.startswith('2001:db8:')):
try:
g[node_by_ll(r.nexthop)].append(node_by_ll(r.prefix)[0])
g[node_by_ll(r.nexthop)].append(
node_by_ll(r.prefix)[0] if r.prefix else default)
except KeyError:
pass
gv = ["digraph { splines = true; edge[color=grey, labelangle=0
, arrowhead=dot
];"]
gv = ["digraph { splines = true; edge[color=grey, labelangle=0];"]
N = len(nodes)
a = 2 * math.pi / N
edges = set()
...
...
@@ -268,17 +279,23 @@ def route_svg(z=4):
l.append((min(j, N - j), p, r))
for j, (l, (p, t), r) in enumerate(sorted(l)):
l = []
arrowhead = 'odot'
for r in sorted(r.short for r in r):
if r == p.short:
r = '
<font
color=
"grey"
>
%s
</font>
' % r
l.append(r)
if r:
if r == p.short:
r = '
<font
color=
"grey"
>
%s
</font>
' % r
l.append(r)
else:
arrowhead = 'dot'
if (n.name, p.name) in edges:
r = 'penwidth=0'
else:
edges.add((p.name, n.name))
r = 'style=solid' if t else 'style=dashed'
gv.append('%s -> %s [labeldistance=%u, headlabel=
<
%
s
>
, %s];'
% (p.name, n.name, 1.5 * math.sqrt(j) + 2, ','.join(l), r))
gv.append(
'%s -> %s [labeldistance=%u, headlabel=
<
%
s
>
, arrowhead=%s, %s];'
% (p.name, n.name, 1.5 * math.sqrt(j) + 2, ','.join(l),
arrowhead, r))
gv.append('}\n')
return subprocess.Popen(('neato', '-Tsvg'),
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
...
...
@@ -288,13 +305,25 @@ if len(sys.argv) > 1:
import SimpleHTTPServer, SocketServer
class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
_path_match = re.compile('/(.+)\.html$').match
pages = 'ipv6', 'ipv4', 'tunnels'
def do_GET(self):
svg = None
if self.path == '/route.html':
other = 'tunnel'
svg = route_svg()
elif self.path == '/tunnel.html':
other = 'route'
try:
page = self.pages.index(self._path_match(self.path).group(1))
except AttributeError, ValueError:
if self.path == '/':
self.send_response(302)
self.send_header('Location', self.pages[0] + '.html')
self.end_headers()
else:
self.send_error(404)
return
if page
<
2:
svg =
route_svg(page)
else:
gv =
registry.Popen(('python',
'
-c
',
r
"""
if
1:
import
math
,
json
from
re6st
.
registry
import
RegistryClient
...
...
@@ -326,21 +355,16 @@ if len(sys.argv) > 1:
if not svg:
self.send_error(500)
return
else:
if self.path == '/':
self.send_response(302)
self.send_header('Location', 'route.html')
self.end_headers()
else:
self.send_error(404)
return
mt = 'text/html'
body = """
<html>
<head><meta
http-equiv=
"refresh"
content=
"10"
/></head>
<body><
a
style=
"position: absolute"
href=
"%s.html"
>
%ss
</a
>
<body><
span
style=
"position: absolute"
>
%s
</span
>
%s
</body>
</html>
""" % (other, other, svg[svg.find('
<svg
')
:
])
</html>
""" % (' '.join(x if i == page else
'
<a
href=
"%s.html"
>
%s
</a>
' % (x, x)
for i, x in enumerate(self.pages)),
svg[svg.find('
<svg
')
:
])
self
.
send_response
(
200
)
self
.
send_header
('
Content-Length
',
len
(
body
))
self
.
send_header
('
Content-type
',
mt
+
';
charset=
utf-8')
...
...
demo/fixnemu.py
0 → 100644
View file @
abf8211e
# -*- coding: utf-8 -*-
# Copyright 2010, 2011 INRIA
# Copyright 2011 Martín Ferrari <martin.ferrari@gmail.com>
#
# This file is contains patches to Nemu.
#
# Nemu is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License version 2, as published by the Free
# Software Foundation.
#
# Nemu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# Nemu. If not, see <http://www.gnu.org/licenses/>.
import
re
from
nemu.iproute
import
backticks
,
get_if_data
,
get_all_route_data
,
route
def
_get_all_route_data
():
ipdata
=
backticks
([
IP_PATH
,
"-o"
,
"route"
,
"list"
])
# "table", "all"
ipdata
+=
backticks
([
IP_PATH
,
"-o"
,
"-f"
,
"inet6"
,
"route"
,
"list"
])
ifdata
=
get_if_data
()[
1
]
ret
=
[]
for
line
in
ipdata
.
split
(
"
\
n
"
):
if
line
==
""
:
continue
# PATCH: parse 'from'
# PATCH: 'dev' is missing on 'unreachable' ipv4 routes
match
=
re
.
match
(
'(?:(unicast|local|broadcast|multicast|throw|'
r'unreachable|prohibit|blackhole|nat) )?(\
S+)(?:
from (\
S+))?
'
r'
(
?
:
via
(
\
S
+
))
?
(
?
:
dev
(
\
S
+
))
?
.
*
(
?
:
metric
(
\
d
+
))
?
', line)
if not match:
raise RuntimeError("Invalid output from `ip route'
:
`
%
s
'" % line)
tipe = match.group(1) or "unicast"
prefix = match.group(2)
#src = match.group(3)
nexthop = match.group(4)
interface = ifdata[match.group(5) or "lo"]
metric = match.group(6)
if prefix == "default" or re.search(r'
/
0
$
', prefix):
prefix = None
prefix_len = 0
else:
match = re.match(r'
([
0
-
9
a
-
f
:.]
+
)(
?
:
/
(
\
d
+
))
?$
', prefix)
prefix = match.group(1)
prefix_len = int(match.group(2) or 32)
ret.append(route(tipe, prefix, prefix_len, nexthop, interface.index,
metric))
return ret
get_all_route_data.func_code = _get_all_route_data.func_code
demo/m1/re6stnet.conf
View file @
abf8211e
...
...
@@ -5,5 +5,5 @@ pp 1194 tcp
ca
ca
.
crt
cert
m1
/
cert
.
crt
key
m1
/
cert
.
key
table
0
default
neighbour
6
/
16
demo/m2/re6stnet.conf
View file @
abf8211e
...
...
@@ -5,4 +5,4 @@ pp 1194 tcp
ca
ca
.
crt
cert
m2
/
cert
.
crt
key
m2
/
cert
.
key
table
0
default
demo/m3/re6stnet.conf
View file @
abf8211e
...
...
@@ -5,4 +5,3 @@ pp 1194 tcp
ca
ca
.
crt
cert
m3
/
cert
.
crt
key
m3
/
cert
.
key
table
0
demo/m4/re6stnet.conf
View file @
abf8211e
...
...
@@ -5,4 +5,4 @@ pp 1194 tcp
ca
ca
.
crt
cert
m4
/
cert
.
crt
key
m4
/
cert
.
key
table
0
default
demo/m5/re6stnet.conf
View file @
abf8211e
...
...
@@ -4,6 +4,6 @@ state m5/
ca
ca
.
crt
cert
m5
/
cert
.
crt
key
m5
/
cert
.
key
table
0
default
client
-
count
0
max
-
clients
0
demo/m6/re6stnet.conf
View file @
abf8211e
...
...
@@ -5,7 +5,7 @@ pp 1194 tcp
ca
ca
.
crt
cert
m6
/
cert
.
crt
key
m6
/
cert
.
key
table
0
default
# TODO: Run a DHCPv4 client on machine9. Unfortunately, isc-dhcp-client 4.2.4
# fails with "Bind socket to interface: No such device"
daemon
"exec dnsmasq -d8 - -i $re6stnet_iface -F 192.168.42.2,192.168.42.254,255.255.255.0,infinite -F ${re6stnet_subnet%/*},ra-only,${re6stnet_subnet#*/},1d -O option:router,192.168.42.1 -l m6/dnsmasq.leases"
demo/m7/re6stnet.conf
View file @
abf8211e
...
...
@@ -5,4 +5,4 @@ pp 1194 tcp
ca
ca
.
crt
cert
m7
/
cert
.
crt
key
m7
/
cert
.
key
table
0
default
demo/m8/re6stnet.conf
View file @
abf8211e
...
...
@@ -4,5 +4,5 @@ state m8/
ca
ca
.
crt
cert
m8
/
cert
.
crt
key
m8
/
cert
.
key
table
0
default
client
10
.
0
.
1
.
2
,
1194
,
tcp
;
10
.
0
.
1
.
3
,
1194
,
tcp
demo/registry/re6st-registry.conf
View file @
abf8211e
...
...
@@ -6,3 +6,4 @@ run registry/run
hello
4
client
-
count
2
tunnel
-
refresh
100
ipv4
10
.
42
.
0
.
0
/
16
8
docs/re6stnet.rst
View file @
abf8211e
...
...
@@ -31,7 +31,7 @@ If you already have IPv6 connectivity by autoconfiguration and still want to
use it for communications that are unrelated to this network, then:
- your kernel must support source address based routing (because you can't
use ``--
table 0
`` option).
use ``--
default
`` option).
- you must set ``net.ipv6.conf.<iface>.accept_ra`` sysctl to value 2 and
trigger SLAAC with ``rdisc6 <iface>`` to restore the default route if the
kernel removed while enabling forwarding.
...
...
@@ -70,7 +70,7 @@ Important note about NetworkManager
It is required to configure properly every connection defined in NetworkManager
because default settings are wrong and conflict with re6st:
- If re6st routes all your IPv6 traffic, using ``--
table 0
`` option, then make
- If re6st routes all your IPv6 traffic, using ``--
default
`` option, then make
sure to disable IPv6 in NetworkManager.
- Otherwise, the following options must be set in [ipv6] section::
...
...
re6st-registry
View file @
abf8211e
...
...
@@ -83,6 +83,9 @@ def main():
_
(
'--anonymous-prefix-length'
,
type
=
int
,
help
=
"Length of allocated anonymous prefixes."
" If 0 or unset, registration by email is required"
)
_
(
'--ipv4'
,
nargs
=
2
,
metavar
=
(
"IP/N"
,
"PLEN"
),
help
=
"Enable ipv4. Each node is assigned a subnet of length PLEN"
" inside network IP/N."
)
_
(
'-l'
,
'--logfile'
,
default
=
'/var/log/re6stnet/registry.log'
,
help
=
"Path to logging file."
)
_
(
'-r'
,
'--run'
,
default
=
'/var/run/re6stnet'
,
...
...
@@ -122,6 +125,15 @@ def main():
parser
.
error
(
"--min-protocol: value must between %s and %s (included)"
%
(
version
.
min_protocol
,
version
.
protocol
))
if
config
.
ipv4
:
ipv4
,
plen
=
config
.
ipv4
try
:
ip
,
n
=
ipv4
.
split
(
'/'
)
config
.
ipv4
=
"%s/%s"
%
(
socket
.
inet_ntoa
(
socket
.
inet_aton
(
ip
)),
int
(
n
)),
int
(
plen
)
except
(
socket
.
error
,
ValueError
):
parser
.
error
(
"invalid argument --ipv4"
)
utils
.
setupLog
(
config
.
verbose
,
config
.
logfile
)
if
config
.
max_clients
is
None
:
...
...
re6st/cache.py
View file @
abf8211e
...
...
@@ -27,7 +27,7 @@ class Cache(object):
q
(
"CREATE INDEX volatile.stat_try ON stat(try)"
)
q
(
"INSERT INTO volatile.stat (peer) SELECT prefix FROM peer"
)
self
.
_db
.
commit
()
self
.
_loadConfig
(
q
(
"SELECT * FROM config"
))
self
.
_loadConfig
(
self
.
_selectConfig
(
q
))
try
:
cert
.
verifyVersion
(
self
.
version
)
except
(
AttributeError
,
x509
.
VerifyError
):
...
...
@@ -63,6 +63,11 @@ class Cache(object):
"value"
)
return
db
@
staticmethod
def
_selectConfig
(
execute
):
# BBB: blob
return
((
k
,
str
(
v
)
if
type
(
v
)
is
buffer
else
v
)
for
k
,
v
in
execute
(
"SELECT * FROM config"
))
def
_loadConfig
(
self
,
config
):
cls
=
self
.
__class__
logging
.
debug
(
"Loading network parameters:"
)
...
...
@@ -98,7 +103,7 @@ class Cache(object):
old
=
{}
with
self
.
_db
as
db
:
remove
=
[]
for
k
,
v
in
db
.
execute
(
"SELECT * FROM config"
):
for
k
,
v
in
self
.
_selectConfig
(
db
.
execute
):
if
k
in
config
:
old
[
k
]
=
v
continue
...
...
@@ -109,8 +114,11 @@ class Cache(object):
remove
.
append
(
k
)
db
.
execute
(
"DELETE FROM config WHERE name in ('%s')"
%
"','"
.
join
(
remove
))
# BBB: Use buffer because of http://bugs.python.org/issue13676
# on Python 2.6
db
.
executemany
(
"INSERT OR REPLACE INTO config VALUES(?,?)"
,
config
.
iteritems
())
((
k
,
buffer
(
v
)
if
k
in
base64
else
v
)
for
k
,
v
in
config
.
iteritems
()))
self
.
_loadConfig
(
config
.
iteritems
())
return
[
k
for
k
,
v
in
config
.
iteritems
()
if
k
not
in
old
or
old
[
k
]
!=
v
]
...
...
re6st/ctl.py
View file @
abf8211e
...
...
@@ -266,6 +266,8 @@ class Babel(object):
a
=
len
(
self
.
network
)
for
route
in
routes
:
assert
route
.
flags
&
1
,
route
# installed
if
route
.
prefix
.
startswith
(
'
\
0
\
0
\
0
\
0
\
0
\
0
\
0
\
0
\
0
\
0
\
xff
\
xff
'
):
continue
assert
route
.
neigh_address
==
route
.
nexthop
,
route
address
=
route
.
neigh_address
,
route
.
ifindex
neigh_routes
=
n
[
address
]
...
...
re6st/plib.py
View file @
abf8211e
...
...
@@ -59,10 +59,11 @@ def client(iface, address_list, encrypt, *args, **kw):
return
openvpn
(
iface
,
encrypt
,
*
remote
,
**
kw
)
def
router
(
subnet
,
hello_interval
,
table
,
log_path
,
state_path
,
pidfile
,
tunnel_interfaces
,
control_socket
,
default
,
*
args
,
**
kw
):
s
=
utils
.
ipFromBin
(
subnet
)
n
=
len
(
subnet
)
def
router
(
ip
,
ip4
,
src
,
hello_interval
,
log_path
,
state_path
,
pidfile
,
control_socket
,
default
,
*
args
,
**
kw
):
ip
,
n
=
ip
if
ip4
:
ip4
,
n4
=
ip4
cmd
=
[
'babeld'
,
'-h'
,
str
(
hello_interval
),
'-H'
,
str
(
hello_interval
),
...
...
@@ -72,16 +73,19 @@ def router(subnet, hello_interval, table, log_path, state_path, pidfile,
'-s'
,
'-C'
,
'default '
+
default
,
'-C'
,
'redistribute local deny'
,
'-C'
,
'redistribute ip %s/%u eq %u'
%
(
s
,
n
,
n
),
'-C'
,
'redistribute deny'
]
if
table
:
cmd
+=
'-t%u'
%
table
,
'-T%u'
%
table
else
:
cmd
[
-
2
:
-
2
]
=
'-C'
,
'redistribute ip ::/0 eq 0'
'-C'
,
'redistribute ip %s/%s eq %s'
%
(
ip
,
n
,
n
)]
if
ip4
:
cmd
+=
'-C'
,
'redistribute ip %s/%s eq %s'
%
(
ip4
,
n4
,
n4
)
if
src
:
cmd
+=
'-C'
,
'install ip ::/0 eq 0 src-prefix '
+
src
elif
src
is
None
:
cmd
+=
'-C'
,
'redistribute ip ::/0 eq 0'
cmd
+=
(
'-C'
,
'redistribute deny'
,
'-C'
,
'install pref-src '
+
ip
)
if
ip4
:
cmd
+=
'-C'
,
'install pref-src '
+
ip4
if
control_socket
:
cmd
+=
'-R'
,
'%s'
%
control_socket
for
iface
in
tunnel_interfaces
:
cmd
+=
'-C'
,
'interface %s legacy-rxcost 5120'
%
iface
cmd
+=
args
# WKRD: babeld fails to start if pidfile already exists
try
:
...
...
re6st/registry.py
View file @
abf8211e
...
...
@@ -60,7 +60,7 @@ class RegistryServer(object):
"name TEXT PRIMARY KEY NOT NULL"
,
"value"
)
self
.
prefix
=
self
.
getConfig
(
"prefix"
,
None
)
self
.
version
=
s
elf
.
getConfig
(
"version"
,
"
\
0
"
)
self
.
version
=
s
tr
(
self
.
getConfig
(
"version"
,
"
\
0
"
))
# BBB: blob
utils
.
sqliteCreateTable
(
self
.
db
,
"token"
,
"token TEXT PRIMARY KEY NOT NULL"
,
"email TEXT NOT NULL"
,
...
...
@@ -119,6 +119,8 @@ class RegistryServer(object):
'protocol'
:
version
.
protocol
,
'registry_prefix'
:
self
.
prefix
,
}
if
self
.
config
.
ipv4
:
kw
[
'ipv4'
],
kw
[
'ipv4_sublen'
]
=
self
.
config
.
ipv4
for
x
in
(
'client_count'
,
'encrypt'
,
'hello'
,
'max_clients'
,
'min_protocol'
,
'tunnel_refresh'
):
kw
[
x
]
=
getattr
(
self
.
config
,
x
)
...
...
@@ -126,7 +128,9 @@ class RegistryServer(object):
if
config
!=
self
.
getConfig
(
'last_config'
,
None
):
self
.
version
=
self
.
encodeVersion
(
1
+
self
.
decodeVersion
(
self
.
version
))
self
.
setConfig
(
'version'
,
self
.
version
)
# BBB: Use buffer because of http://bugs.python.org/issue13676
# on Python 2.6
self
.
setConfig
(
'version'
,
buffer
(
self
.
version
))
self
.
setConfig
(
'last_config'
,
config
)
self
.
sendto
(
self
.
prefix
,
0
)
kw
[
''
]
=
'version'
,
...
...
re6st/tunnel.py
View file @
abf8211e
...
...
@@ -168,7 +168,8 @@ class BaseTunnelManager(object):
# TODO: To minimize downtime when network parameters change, we should do
# our best to not restart any process. Ideally, this list should be
# empty and the affected subprocesses reloaded.
NEED_RESTART
=
frozenset
((
'babel_default'
,
'encrypt'
,
'hello'
))
NEED_RESTART
=
frozenset
((
'babel_default'
,
'encrypt'
,
'hello'
,
'ipv4'
,
'ipv4_sublen'
))
_forward
=
None
...
...
re6stnet
View file @
abf8211e
#!/usr/bin/python
import
atexit
,
errno
,
logging
,
os
,
shutil
,
signal
import
socket
,
subprocess
,
sys
,
time
,
threading
import
socket
,
s
truct
,
s
ubprocess
,
sys
,
time
,
threading
from
collections
import
deque
from
functools
import
partial
from
re6st
import
plib
,
tunnel
,
utils
,
version
,
x509
...
...
@@ -58,11 +58,13 @@ def getConfig():
_
=
parser
.
add_argument_group
(
'routing'
).
add_argument
_
(
'-B'
,
dest
=
'babel_args'
,
metavar
=
'ARG'
,
action
=
'append'
,
default
=
[],
help
=
"Extra arguments to forward to Babel."
)
_
(
'--table'
,
type
=
int
,
default
=
42
,
help
=
"Use given table id. Set 0 to use the main table, if you want to"
" access internet via this network (in this case, make sure you"
" don't already have a default route). Don't use this option with"
" --gateway (main table is automatically used)."
)
_
(
'-D'
,
'--default'
,
action
=
'store_true'
,
help
=
"Access internet via this network (in this case, make sure you"
" don't already have a default route), or if your kernel was"
" compiled without support for source address based routing"
" (CONFIG_IPV6_SUBTREES). Meaningless with --gateway."
)
_
(
'--table'
,
type
=
int
,
choices
=
(
0
,),
help
=
"DEPRECATED: Use --default instead of --table=0"
)
_
(
'--gateway'
,
action
=
'store_true'
,
help
=
"Act as a gateway for this network (the default route will be"
" exported). Do never use it if you don't know what it means."
)
...
...
@@ -140,9 +142,15 @@ def main():
if
config
.
max_clients
is
None
:
config
.
max_clients
=
cache
.
max_clients
if
config
.
table
is
not
None
:
logging
.
warning
(
"--table option is deprecated: use --default instead"
)
config
.
default
=
True
if
config
.
default
and
config
.
gateway
:
sys
.
exit
(
"error: conflicting options --default and --gateway"
)
if
'none'
in
config
.
disable_proto
:
config
.
disable_proto
=
()
if
not
config
.
table
:
if
config
.
default
:
# Make sure we won't tunnel over re6st.
config
.
disable_proto
=
tuple
(
set
((
'tcp6'
,
'udp6'
)).
union
(
config
.
disable_proto
))
...
...
@@ -221,6 +229,11 @@ def main():
raise
EnvironmentError
(
"%r failed with error %u
\
n
%s"
%
(
' '
.
join
(
cmd
),
p
.
returncode
,
stderr
))
return
stdout
def
ip4
(
object
,
*
args
):
args
=
[
'ip'
,
'-4'
,
object
,
'add'
]
+
list
(
args
)
call
(
args
)
args
[
3
]
=
'del'
cleanup
.
append
(
lambda
:
subprocess
.
call
(
args
))
def
ip
(
object
,
*
args
):
args
=
[
'ip'
,
'-6'
,
object
,
'add'
]
+
list
(
args
)
call
(
args
)
...
...
@@ -236,10 +249,9 @@ def main():
os
.
environ
[
're6stnet_iface'
]
=
config
.
main_interface
os
.
environ
[
're6stnet_subnet'
]
=
my_subnet
os
.
environ
[
're6stnet_network'
]
=
my_network
my_ip
+=
'/%s'
%
len
(
subnet
)
# Init db and tunnels
tunnel_interfaces
=
server_tunnels
.
keys
()
config
.
babel_args
+=
server_tunnels
timeout
=
4
*
cache
.
hello
cleanup
=
[
lambda
:
cache
.
cacheMinimize
(
config
.
client_count
),
lambda
:
shutil
.
rmtree
(
config
.
run
,
True
)]
...
...
@@ -250,29 +262,48 @@ def main():
cache
,
cert
,
config
.
openvpn_args
,
timeout
,
config
.
client_count
,
config
.
iface_list
,
address
,
ip_changed
,
remote_gateway
,
config
.
disable_proto
,
config
.
neighbour
)
tunnel_interface
s
+=
tunnel_manager
.
new_iface_list
config
.
babel_arg
s
+=
tunnel_manager
.
new_iface_list
else
:
tunnel_manager
=
tunnel
.
BaseTunnelManager
(
cache
,
cert
)
cleanup
.
append
(
tunnel_manager
.
sock
.
close
)
try
:
exit
.
acquire
()
# Source address selection is defined by RFC 6724, and in most
# applications, it usually works thanks to rule 5 (prefer outgoing
# interface). But here, it rarely applies because we use several
# interfaces to connect to a re6st network.
# Rule 7 is little strange because it prefers temporary addresses
# over IP with a longer matching prefix (rule 8, which is not even
# mandatory).
# So only rule 6 can make the difference, i.e. prefer same label.
# The value of the label does not matter, except that it must be
# different from ::/0's (normally equal to 1).
# XXX: This does not work with extra interfaces that already have
# an public IP so Babel must be changed to set a source
# address on routes it installs.
ip
(
'addrlabel'
,
'prefix'
,
my_network
,
'label'
,
'99'
)
ipv4
=
getattr
(
cache
,
'ipv4'
,
None
)
if
ipv4
:
serial
=
int
(
cert
.
cert
.
get_subject
().
serialNumber
)
if
cache
.
ipv4_sublen
<=
16
and
serial
<
1
<<
cache
.
ipv4_sublen
:
dot4
=
lambda
x
:
socket
.
inet_ntoa
(
struct
.
pack
(
'!I'
,
x
))
ip4
(
'route'
,
'unreachable'
,
ipv4
,
'proto'
,
'static'
)
ipv4
,
n
=
ipv4
.
split
(
'/'
)
ipv4
,
=
struct
.
unpack
(
'!I'
,
socket
.
inet_aton
(
ipv4
))
n
=
int
(
n
)
+
cache
.
ipv4_sublen
x
=
ipv4
|
serial
<<
32
-
n
ipv4
=
dot4
(
x
|
(
n
<
31
))
config
.
openvpn_args
+=
'--ifconfig'
,
\
ipv4
,
dot4
((
1
<<
32
)
-
(
1
<<
32
-
n
))
ipv4
=
ipv4
,
n
if
not
isinstance
(
tunnel_manager
,
tunnel
.
TunnelManager
):
ip4
(
'addr'
,
"%s/%s"
%
ipv4
,
'dev'
,
config
.
main_interface
)
if
config
.
main_interface
==
"lo"
:
ip4
(
'route'
,
'unreachable'
,
"%s/%s"
%
(
dot4
(
x
),
n
),
'proto'
,
'static'
)
else
:
logging
.
warning
(
"IPv4 payload disabled due to wrong network parameters"
)
ipv4
=
None
if
os
.
uname
()[
2
]
<
'2.6.40'
:
# BBB
logging
.
warning
(
"Fallback to ip-addrlabel because Linux < 3.0"
" does not support RTA_PREFSRC for ipv6. Note however that"
" this workaround does not work with extra interfaces that"
" already have a public IP"
)
ip
(
'addrlabel'
,
'prefix'
,
my_network
,
'label'
,
'99'
)
# No need to tell babeld not to set a preferred source IP in
# installed routes. The kernel will silently discard the option.
R
=
{}
# prepare persistent interfaces
if
config
.
client
:
address_list
=
[
x
for
x
in
utils
.
parse_address
(
config
.
client
)
if
x
[
2
]
not
in
config
.
disable_proto
]
...
...
@@ -296,7 +327,8 @@ def main():
R
[
r
]
=
partial
(
tunnel_manager
.
handleServerEvent
,
r
)
x
.
close
()
ip
(
'addr'
,
my_ip
,
'dev'
,
config
.
main_interface
)
ip
(
'addr'
,
my_ip
+
'/%s'
%
len
(
subnet
),
'dev'
,
config
.
main_interface
)
if_rt
=
[
'ip'
,
'-6'
,
'route'
,
'del'
,
'fe80::/64'
,
'dev'
,
config
.
main_interface
]
if
config
.
main_interface
==
'lo'
:
...
...
@@ -305,30 +337,13 @@ def main():
subprocess
.
call
(
if_rt
)
if_rt
[
4
]
=
my_subnet
cleanup
.
append
(
lambda
:
subprocess
.
call
(
if_rt
))
x
=
[
my_network
]
if
config
.
gateway
:
config
.
table
=
0
elif
config
.
table
:
x
+=
'table'
,
str
(
config
.
table
)
try
:
ip
(
'rule'
,
'from'
,
*
x
)
except
EnvironmentError
:
logging
.
error
(
"It seems that your kernel was compiled"
" without support for source address based routing"
" (CONFIG_IPV6_SUBTREES). Consider using --table=0"
" option if you can't change your kernel."
)
raise
ip
(
'rule'
,
'to'
,
*
x
)
call
(
if_rt
)
if_rt
+=
x
[
1
:]
call
(
if_rt
[:
3
]
+
[
'add'
,
'proto'
,
'static'
]
+
if_rt
[
4
:])
else
:
if
config
.
default
:
def
check_no_default_route
():
for
route
in
call
((
'ip'
,
'-6'
,
'route'
,
'show'
,
'default'
)).
splitlines
():
if
' proto 42 '
not
in
route
:
sys
.
exit
(
"Detected default route (%s)"
" whereas you specified --
table=0
."
" whereas you specified --
default
."
" Fix your configuration."
%
route
)
check_no_default_route
()
def
check_no_default_route_thread
():
...
...
@@ -347,14 +362,17 @@ def main():
t
=
threading
.
Thread
(
target
=
check_no_default_route_thread
)
t
.
daemon
=
True
t
.
start
()
ip
(
'route'
,
'unreachable'
,
*
x
)
ip
(
'route'
,
'unreachable'
,
my_network
)
config
.
babel_args
+=
config
.
iface_list
cleanup
.
append
(
plib
.
router
(
subnet
,
cache
.
hello
,
config
.
table
,
cleanup
.
append
(
plib
.
router
((
my_ip
,
len
(
subnet
)),
ipv4
,
None
if
config
.
gateway
else
''
if
config
.
default
else
my_network
,
cache
.
hello
,
os
.
path
.
join
(
config
.
log
,
'babeld.log'
),
os
.
path
.
join
(
config
.
state
,
'babeld.state'
),
os
.
path
.
join
(
config
.
run
,
'babeld.pid'
),
tunnel_interfaces
,
control_socket
,
cache
.
babel_default
,
control_socket
,
cache
.
babel_default
,
*
config
.
babel_args
).
stop
)
if
config
.
up
:
exit
.
release
()
...
...
re6stnet.spec
View file @
abf8211e
...
...
@@ -8,7 +8,7 @@ Release: %(set %ver; echo ${1#*-})
License: GPLv2+
Group: Applications/Internet
BuildArch: noarch
Requires: babeld = 1.
5.1-nxd2
Requires: babeld = 1.
6-git0.8950d3b.nxd1
Requires: iproute
Requires: openssl
Requires: openvpn
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment