X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=gui%2Ftinc-gui;h=9534167d6be9a18c6c54f67385dc3e04f0d0ab89;hp=e5c9f76647549dea371359ef09ecec1a844ef3c8;hb=386c1aff08a3ce6e295931e2fcf4bfc607053ff0;hpb=ce8775000ab38229a78ecf3dc26bab008ca0f332 diff --git a/gui/tinc-gui b/gui/tinc-gui index e5c9f766..9534167d 100755 --- a/gui/tinc-gui +++ b/gui/tinc-gui @@ -1,11 +1,227 @@ #!/usr/bin/python +import string +import socket import wx import sys -import Tinc from wx.lib.mixins.listctrl import ColumnSorterMixin from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin +# Classes to interface with a running tinc daemon + +REQ_STOP = 0 +REQ_RELOAD = 1 +REQ_RESTART = 2 +REQ_DUMP_NODES = 3 +REQ_DUMP_EDGES = 4 +REQ_DUMP_SUBNETS = 5 +REQ_DUMP_CONNECTIONS = 6 +REQ_DUMP_GRAPH = 7 +REQ_PURGE = 8 +REQ_SET_DEBUG = 9 +REQ_RETRY = 10 +REQ_CONNECT = 11 +REQ_DISCONNECT = 12 + +ID = 0 +ACK = 4 +CONTROL = 18 + +class Node: + def __init__(self): + print('New node') + + def __exit__(self): + print('Deleting node ' + self.name) + + def parse(self, args): + self.name = args[0] + self.address = args[2] + if args[3] != 'port': + args.insert(3, 'port') + args.insert(4, '') + self.port = args[4] + self.cipher = int(args[6]) + self.digest = int(args[8]) + self.maclength = int(args[10]) + self.compression = int(args[12]) + self.options = int(args[14], 0x10) + self.status = int(args[16], 0x10) + self.nexthop = args[18] + self.via = args[20] + self.distance = int(args[22]) + self.pmtu = int(args[24]) + self.minmtu = int(args[26]) + self.maxmtu = int(args[28][:-1]) + + self.subnets = {} + +class Edge: + def parse(self, args): + self.fr = args[0] + self.to = args[2] + self.address = args[4] + self.port = args[6] + self.options = int(args[8], 16) + self.weight = int(args[10]) + +class Subnet: + def parse(self, args): + if args[0].find('#') >= 0: + (address, self.weight) = args[0].split('#', 1) + else: + self.weight = 10 + address = args[0] + + if address.find('/') >= 0: + (self.address, self.prefixlen) = address.split('/', 1) + else: + self.address = address + self.prefixlen = '48' + + self.owner = args[2] + +class Connection: + def parse(self, args): + self.name = args[0] + self.address = args[2] + if args[3] != 'port': + args.insert(3, 'port') + args.insert(4, '') + self.port = args[4] + self.options = int(args[6], 0x10) + self.socket = int(args[8]) + self.status = int(args[10], 0x10) + self.weight = 123 + +class VPN: + confdir = '/etc/tinc' + cookiedir = '/var/run/' + + def connect(self): + f = open(self.cookiefile) + cookie = string.split(f.readline()) + f.close() + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(('127.0.0.1', int(cookie[1]))) + self.sf = s.makefile() + s.close() + hello = string.split(self.sf.readline()) + self.name = hello[1] + self.sf.write('0 ^' + cookie[0] + ' 17\r\n') + self.sf.flush() + resp = string.split(self.sf.readline()) + self.port = cookie[1] + self.nodes = {} + self.edges = {} + self.subnets = {} + self.connections = {} + self.refresh() + + def refresh(self): + self.sf.write('18 3\r\n18 4\r\n18 5\r\n18 6\r\n') + self.sf.flush() + + for node in self.nodes.values(): + node.visited = False + for edge in self.edges.values(): + edge.visited = False + for subnet in self.subnets.values(): + subnet.visited = False + for connections in self.connections.values(): + connections.visited = False + + while True: + resp = string.split(self.sf.readline()) + if len(resp) < 2: + break + if resp[0] != '18': + break + if resp[1] == '3': + if len(resp) < 3: + continue + node = self.nodes.get(resp[2]) or Node() + node.parse(resp[2:]) + node.visited = True + self.nodes[resp[2]] = node + elif resp[1] == '4': + if len(resp) < 5: + continue + edge = self.nodes.get((resp[2], resp[4])) or Edge() + edge.parse(resp[2:]) + edge.visited = True + self.edges[(resp[2], resp[4])] = edge + elif resp[1] == '5': + if len(resp) < 5: + continue + subnet = self.subnets.get((resp[2], resp[4])) or Subnet() + subnet.parse(resp[2:]) + subnet.visited = True + self.subnets[(resp[2], resp[4])] = subnet + self.nodes[subnet.owner].subnets[resp[2]] = subnet + elif resp[1] == '6': + if len(resp) < 5: + break + connection = self.connections.get((resp[2], resp[4])) or Connection() + connection.parse(resp[2:]) + connection.visited = True + self.connections[(resp[2], resp[4])] = connection + else: + break + + for key, subnet in self.subnets.items(): + if not subnet.visited: + del self.subnets[key] + + for key, edge in self.edges.items(): + if not edge.visited: + del self.edges[key] + + for key, node in self.nodes.items(): + if not node.visited: + del self.nodes[key] + else: + for key, subnet in node.subnets.items(): + if not subnet.visited: + del node.subnets[key] + + for key, connection in self.connections.items(): + if not connection.visited: + del self.connections[key] + + def close(self): + self.sf.close() + + def disconnect(self, name): + self.sf.write('18 12 ' + name + '\r\n') + self.sf.flush() + resp = string.split(self.sf.readline()) + + def debug(self, level = -1): + self.sf.write('18 9 ' + str(level) + '\r\n') + self.sf.flush() + resp = string.split(self.sf.readline()) + return int(resp[2]) + + def __init__(self, netname = None, controlcookie = None): + self.tincconf = VPN.confdir + '/' + + if netname: + self.netname = netname + self.tincconf += netname + '/' + + self.tincconf += 'tinc.conf' + + if controlcookie is not None: + self.cookiefile = controlcookie + else: + self.cookiefile = VPN.cookiedir + 'tinc.' + if netname: + self.cookiefile += netname + '.' + self.cookiefile += 'cookie' + +# GUI starts here + del sys.argv[0] net = None controlcookie = None @@ -22,7 +238,7 @@ while len(sys.argv) >= 2: del sys.argv[0] del sys.argv[0] -vpn = Tinc.VPN(net, controlcookie) +vpn = VPN(net, controlcookie) vpn.connect() class SuperListCtrl(wx.ListCtrl, ColumnSorterMixin, ListCtrlAutoWidthMixin): @@ -107,7 +323,7 @@ class ConnectionsPage(wx.Panel): i = 0 for key, connection in vpn.connections.items(): - if self.list.ItemCount <= i: + if self.list.GetItemCount() <= i: self.list.InsertStringItem(i, connection.name) else: self.list.SetStringItem(i, 0, connection.name) @@ -119,8 +335,8 @@ class ConnectionsPage(wx.Panel): self.list.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnContext) i += 1 - while self.list.ItemCount > i: - self.list.DeleteItem(self.list.ItemCount - 1) + while self.list.GetItemCount() > i: + self.list.DeleteItem(self.list.GetItemCount() - 1) class NodesPage(wx.Panel): @@ -153,7 +369,7 @@ class NodesPage(wx.Panel): i = 0 for key, node in vpn.nodes.items(): - if self.list.ItemCount <= i: + if self.list.GetItemCount() <= i: self.list.InsertStringItem(i, node.name) else: self.list.SetStringItem(i, 0, node.name) @@ -175,8 +391,8 @@ class NodesPage(wx.Panel): self.list.SetItemData(i, i) i += 1 - while self.list.ItemCount > i: - self.list.DeleteItem(self.list.ItemCount - 1) + while self.list.GetItemCount() > i: + self.list.DeleteItem(self.list.GetItemCount() - 1) class EdgesPage(wx.Panel): def __init__(self, parent, id): @@ -199,7 +415,7 @@ class EdgesPage(wx.Panel): i = 0 for key, edge in vpn.edges.items(): - if self.list.ItemCount <= i: + if self.list.GetItemCount() <= i: self.list.InsertStringItem(i, edge.fr) else: self.list.SetStringItem(i, 0, edge.fr) @@ -211,8 +427,8 @@ class EdgesPage(wx.Panel): self.list.itemDataMap[i] = (edge.fr, edge.to, edge.address, edge.port, edge.options, edge.weight) i += 1 - while self.list.ItemCount > i: - self.list.DeleteItem(self.list.ItemCount - 1) + while self.list.GetItemCount() > i: + self.list.DeleteItem(self.list.GetItemCount() - 1) class SubnetsPage(wx.Panel): def __init__(self, parent, id): @@ -231,7 +447,7 @@ class SubnetsPage(wx.Panel): i = 0 for key, subnet in vpn.subnets.items(): - if self.list.ItemCount <= i: + if self.list.GetItemCount() <= i: self.list.InsertStringItem(i, subnet.address + '/' + subnet.prefixlen) else: self.list.SetStringItem(i, 0, subnet.address + '/' + subnet.prefixlen) @@ -240,8 +456,8 @@ class SubnetsPage(wx.Panel): self.list.itemDataMap[i] = (subnet.address + '/' + subnet.prefixlen, subnet.weight, subnet.owner) i = i + 1 - while self.list.ItemCount > i: - self.list.DeleteItem(self.list.ItemCount - 1) + while self.list.GetItemCount() > i: + self.list.DeleteItem(self.list.GetItemCount() - 1) class StatusPage(wx.Panel): def __init__(self, parent, id):