Commit 6452f083 authored by Ulysse Beaugnon's avatar Ulysse Beaugnon

Merge branch 'master' of https://git.erp5.org/repos/vifibnet

parents bde5fdec 1d46fa73
#!/usr/bin/python -S
import os, sys
os.write(int(sys.argv[1]), '%(script_type)s %(external_ip)s\n' % os.environ)
......@@ -20,10 +20,6 @@ class main(object):
parser = argparse.ArgumentParser(
description='Peer discovery http server for vifibnet')
_ = parser.add_argument
_('--prefix', required=True,
help='Prefix of the network deployed ( example : 2001:db8:42')
_('--prefix-len', required=True, type=int,
help='Prefix length')
_('--db', required=True,
help='Path to database file')
_('--ca', required=True,
......@@ -52,9 +48,7 @@ class main(object):
email text,
cert text)""")
except sqlite3.OperationalError, e:
if e.args[0] == 'table vifib already exists':
pass
else:
if e.args[0] != 'table vifib already exists':
raise RuntimeError
else:
self.db.execute("INSERT INTO vifib VALUES ('',null,null)")
......@@ -67,6 +61,7 @@ class main(object):
self.key = crypto.load_privatekey(crypto.FILETYPE_PEM, f.read())
# Get vifib network prefix
self.network = bin(self.ca.get_serial_number())[3:]
print "Network prefix : %s/%u" % (self.network, len(self.network))
# Starting server
server = SimpleXMLRPCServer(("localhost", 8000), requestHandler=RequestHandler, allow_none=True)
......@@ -147,22 +142,28 @@ class main(object):
client_address, _ = handler.client_address
# For Testing purposes only
client_address = "2001:db8:42::"
assert(client_address.startswith(self.config.prefix))
ip1, ip2 = struct.unpack('>QQ', socket.inet_pton(socket.AF_INET6, client_address))
ip1 = bin(ip1)[2:].rjust(64, '0')
ip2 = bin(ip2)[2:].rjust(64, '0')
prefix = (ip1 + ip2)[self.config.prefix_len:]
prefix, = self.db.execute("SELECT prefix FROM vifib WHERE prefix <= ? ORDER BY prefix DESC", (prefix,)).next()
ip, port, proto = address
self.db.execute("INSERT OR REPLACE INTO peers VALUES (?,?,?,?)", (prefix, ip, port, proto))
ip = bin(ip1)[2:].rjust(64, '0') + bin(ip2)[2:].rjust(64, '0')
if ip.startswith(self.network):
prefix = ip[len(self.network):]
prefix, = self.db.execute("SELECT prefix FROM vifib WHERE prefix <= ? ORDER BY prefix DESC", (prefix,)).next()
ip, port, proto = address
self.db.execute("INSERT OR REPLACE INTO peers VALUES (?,?,?,?)", (prefix, ip, port, proto))
return True
else:
print "Unauthorized connection from %s which does not start with %s" % (ip, self.network)
return False
def getPeerList(self, handler, n, address):
assert 0 < n < 1000
print "declaring new node"
self.declare(handler, address)
if not self.declare(handler, address):
# TODO: do something intelligent
raise RuntimeError
print "sending peers"
return self.db.execute("SELECT ip, port, proto FROM peers ORDER BY random() LIMIT ?", (n,)).fetchall()
if __name__ == "__main__":
main()
......@@ -18,7 +18,7 @@ def main():
config = parser.parse_args()
if config.req and len(config.req) % 2 == 1:
print "Sorry, request argument was incorrect, there must be an even number of request arguments"
os.exit(1)
exit(1)
# Get token
email = raw_input('Please enter your email address : ')
......@@ -44,7 +44,7 @@ def main():
# Get certificates
ca = s.getCa()
cert = s.requestCertificate(token,req)
cert = s.requestCertificate(token, req)
# Generating dh file
subprocess.call(['openssl', 'dhparam', '-out', os.path.join(config.dir, 'dh2048.pem'), '2048'])
......
......@@ -7,13 +7,12 @@ import openvpn
import random
import log
VIFIB_NET = "2001:db8:42:"
VIFIB_LEN = 48
VIFIB_NET = ''
connection_dict = {} # to remember current connections we made
free_interface_set = set(('client1', 'client2', 'client3', 'client4', 'client5',
'client6', 'client7', 'client8', 'client9', 'client10'))
# TODO : flag in some way the peers that are connected to us so we don't connect to them
# TODO: flag in some way the peers that are connected to us so we don't connect to them
# Or maybe we just don't care
class PeersDB:
......@@ -57,21 +56,24 @@ class PeersDB:
log.log('Updating peers database : unusing peer ' + str(id), 5)
self.db.execute("UPDATE peers SET used = 0 WHERE id = ?", (id,))
# TODO: do everything using 'binary' strings
def ipFromBin(prefix):
prefix = hex(int(prefix, 2))[2:]
ip = ''
for i in xrange(0, len(prefix) - 1, 4):
ip += prefix[i:i+4] + ':'
return ip.rstrip(':')
def ipFromPrefix(prefix, prefix_len):
tmp = hex(int(prefix))[2:]
tmp = tmp.rjust(int((math.ceil(float(prefix_len) / 4))), '0')
ip = VIFIB_NET
for i in xrange(0, len(tmp), 4):
ip += tmp[i:i+4] + ':'
return ip + ':'
prefix = bin(int(prefix))[2:].rjust(prefix_len, '0')
ip_t = (config.vifibnet + prefix).ljust(128, '0')
return ipFromBin(ip_t)
def startBabel(**kw):
args = ['babeld',
'-C', 'redistribute local ip %s' % (config.ip),
'-C', 'redistribute local deny',
# Route VIFIB ip adresses
'-C', 'in ip %s:/%u' % (VIFIB_NET, VIFIB_LEN),
'-C', 'in ip %s::/%u' % (ipFromBin(config.vifibnet), len(config.vifibnet)),
# Route only addresse in the 'local' network,
# or other entire networks
#'-C', 'in ip %s' % (config.ip),
......@@ -98,7 +100,7 @@ def getConfig():
help='Path to vifibnet logs directory')
_('--client-count', default=2, type=int,
help='Number of client connections')
# TODO : use maxpeer
# TODO: use maxpeer
_('--max-clients', default=10, type=int,
help='the number of peers that can connect to the server')
_('--refresh-time', default=60, type=int,
......@@ -113,57 +115,63 @@ def getConfig():
help='Path to babeld state-file')
_('--verbose', '-v', default=0, type=int,
help='Defines the verbose level')
_('--ca', required=True,
help='Path to the certificate authority file')
_('--cert', required=True,
help='Path to the certificate file')
# Temporary args - to be removed
# Can be removed, should ip be a global variable ?
_('--ip', required=True,
help='IPv6 of the server')
# Openvpn options
_('openvpn_args', nargs=argparse.REMAINDER,
help="Common OpenVPN options (e.g. certificates)")
openvpn.config = config = parser.parse_args()
log.verbose = config.verbose
# Get network prefix from ca.crt
with open(config.ca, 'r') as f:
ca = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
config.vifibnet = bin(ca.get_serial_number())[3:]
# Get ip from cert.crt
with open(config.cert, 'r') as f:
cert = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
subject = cert.get_subject()
prefix, prefix_len = subject.serialNumber.split('/')
ip = ipFromPrefix(prefix, int(prefix_len))
log.log('Intranet ip : %s' % (ip,), 3)
config.ip = ipFromPrefix(prefix, int(prefix_len))
log.log('Intranet ip : %s' % (config.ip,), 3)
# Treat openvpn arguments
if config.openvpn_args[0] == "--":
del config.openvpn_args[0]
config.openvpn_args.append('--ca')
config.openvpn_args.append(config.ca)
config.openvpn_args.append('--cert')
config.openvpn_args.append(config.cert)
log.log("Configuration completed", 1)
def startNewConnection(n, write_pipe):
try:
for id, ip, port, proto in peers_db.getUnusedPeers(n):
log.log('Establishing a connection with id %s (%s:%s)' % (id,ip,port), 2)
for peer_id, ip, port, proto in peers_db.getUnusedPeers(n):
log.log('Establishing a connection with id %s (%s:%s)' % (peer_id, ip, port), 2)
iface = free_interface_set.pop()
connection_dict[id] = ( openvpn.client( ip, write_pipe, '--dev', iface, '--proto', proto, '--rport', str(port),
stdout=os.open(os.path.join(config.log, 'vifibnet.client.%s.log' % (id,)),
connection_dict[peer_id] = ( openvpn.client( ip, write_pipe, '--dev', iface, '--proto', proto, '--rport', str(port),
stdout=os.open(os.path.join(config.log, 'vifibnet.client.%s.log' % (peer_id,)),
os.O_WRONLY|os.O_CREAT|os.O_TRUNC) ),
iface)
peers_db.usePeer(id)
peers_db.usePeer(peer_id)
except KeyError:
log.log("Can't establish connection with %s : no available interface" % ip, 2)
pass
except Exception:
traceback.print_exc()
def killConnection(id):
def killConnection(peer_id):
try:
log.log('Killing the connection with id ' + str(id), 2)
p, iface = connection_dict.pop(id)
log.log('Killing the connection with id ' + str(peer_id), 2)
p, iface = connection_dict.pop(peer_id)
p.kill()
free_interface_set.add(iface)
peers_db.unusePeer(id)
peers_db.unusePeer(peer_id)
except KeyError:
log.log("Can't kill connection to " + peer + ": no existing connection", 1)
log.log("Can't kill connection to " + peer_id + ": no existing connection", 1)
pass
except Exception:
log.log("Can't kill connection to " + peer + ": uncaught error", 1)
log.log("Can't kill connection to " + peer_id + ": uncaught error", 1)
pass
def checkConnections():
......@@ -175,23 +183,23 @@ def checkConnections():
peers_db.unusePeer(id)
del connection_dict[id]
def refreshConnections():
def refreshConnections(write_pipe):
checkConnections()
# Kill some random connections
try:
for i in range(0, max(0, len(connection_dict) - config.client_count + config.refresh_count)):
id = random.choice(connection_dict.keys())
killConnection(id)
peer_id = random.choice(connection_dict.keys())
killConnection(peer_id)
except Exception:
pass
# Establish new connections
startNewConnection(config.client_count - len(connection_dict))
startNewConnection(config.client_count - len(connection_dict), write_pipe)
def handle_message(msg):
script_type, arg = msg.split()
if script_type == 'client-connect':
log.log('Incomming connection from %s' % (arg,), 3)
# TODO : check if we are not already connected to it
# TODO: check if we are not already connected to it
elif script_type == 'client-disconnect':
log.log('%s has disconnected' % (arg,), 3)
elif script_type == 'ipchange':
......@@ -237,7 +245,7 @@ def main():
if ready:
handle_message(read_pipe.readline())
if time.time() >= next_refresh:
refreshConnections()
refreshConnections(write_pipe)
next_refresh = time.time() + config.refresh_time
except KeyboardInterrupt:
return 0
......
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