From b97e85feef6b4dad4add23d17e37fd5ee976e1e3 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Mon, 24 May 2010 22:04:07 +0200 Subject: Added IPv6 support. This currently needs the destination host to be stored in host6. The local address can be bound by setting bind6. --- fot.py | 10 ++++-- ipv6.py | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 ipv6.py diff --git a/fot.py b/fot.py index 8412e8c..75cdfaf 100755 --- a/fot.py +++ b/fot.py @@ -9,7 +9,7 @@ import os from ConfigParser import ConfigParser -import login +import login, ipv6 config = ConfigParser() @@ -130,9 +130,13 @@ for server in (server for server in config.sections() if server.startswith('serv ch = [x[0] for x in ms if c in x[1]] channels.append('%s (%s)' % (c, ' '.join(ch))) print '%s: %s' % (server, ' '.join(channels)) - del channels, ms, c, ch, x + #del channels, ms, c, ch, x factory = BotFactory(server, config.get(server, 'nickname')) - reactor.connectTCP(config.get(server, 'host'), config.getint(server, 'port'), factory) + if config.has_option(server, 'host6'): + bind6 = (config.get(server, 'bind6'), 0) if config.has_option(server, 'bind6') else None + ipv6.connectTCP6(config.get(server, 'host6'), config.getint(server, 'port6'), factory, bindAddress = bind6) + else: + reactor.connectTCP(config.get(server, 'host'), config.getint(server, 'port'), factory) loginfactory = login.getManholeFactory(globals(), os.path.expanduser('~/.fot.users')) reactor.listenTCP(3333, loginfactory) diff --git a/ipv6.py b/ipv6.py new file mode 100644 index 0000000..eb6ce2e --- /dev/null +++ b/ipv6.py @@ -0,0 +1,116 @@ + +import socket +from twisted.internet import tcp +from twisted.internet import default +from twisted.internet import protocol +from twisted.internet import reactor + +class IPv6Address(object): + def __init__(self, type, host, port, flowInfo, scope): + self.type = type + self.host = host + self.port = port + self.flowInfo = flowInfo + self.scope = scope + + def __eq__(self, other): + if isinstance(other, IPv6Address): + a = (self.type, self.host, self.port, self.flowInfo, self.scope) + b = (other.type, other.host, other.port, other.flowInfo, other.scope) + return a == b + return False + + def __str__(self): + return 'IPv6Address(%s, %r, %d, %d, %d)' % ( + self.type, self.host, self.port, self.flowInfo, self.scope) + +def isIPv6Address(ip): + try: + socket.inet_pton(socket.AF_INET6, ip) + except: + return 0 + return 1 + +class Client(tcp.Client): + addressFamily = socket.AF_INET6 + + def resolveAddress(self): + if isIPv6Address(self.addr[0]): + self._setRealAddress(self.addr[0]) + else: + reactor.resolve(self.addr[0]).addCallbacks( + self._setRealAddress, self.failIfNotConnected + ) + + def getHost(self): + return IPv6Address('TCP', *self.socket.getsockname()) + + def getPeer(self): + return IPv6Address('TCP', *self.socket.getpeername()) + + +class Connector(tcp.Connector): + def _makeTransport(self): + return Client(self.host, self.port, self.bindAddress, self, self.reactor) + + def getDestination(self): + return IPv6Address('TCP', self.host, self.port) + +class Server(tcp.Server): + def getHost(self): + return IPv6Address('TCP', *self.socket.getsockname()) + + def getPeer(self): + return IPv6Address('TCP', *self.client) + +class Port(tcp.Port): + addressFamily = socket.AF_INET6 + + transport = Server + + def _buildAddr(self, address): + return IPv6Address('TCP', *address) + + def getHost(self): + return IPv6Address('TCP', *self.socket.getsockname()) + + def getPeer(self): + return IPv6Address('TCP', *self.socket.getpeername()) + +def connectTCP6(host, port, factory, timeout=30, bindAddress=None, reactor=None): + if reactor is None: + from twisted.internet import reactor + return reactor.connectWith( + Connector, host, port, factory, timeout, bindAddress + ) + + +def listenTCP6(port, factory, backlog=5, interface='::', reactor=None): + if reactor is None: + from twisted.internet import reactor + return reactor.listenWith(Port, port, factory, backlog, interface) + +def main(): + from twisted.internet import reactor + + class TrivialProtocol(protocol.Protocol): + def connectionMade(self): + print 'I (', self.transport.getHost(), ') am connected! (to ', self.transport.getPeer(), ')' + self.transport.write('Hello, world!\n') + + def dataReceived(self, data): + print 'Received: ' + repr(data) + + class TrivialServerFactory(protocol.ServerFactory): + protocol = TrivialProtocol + class TrivialClientFactory(protocol.ClientFactory): + protocol = TrivialProtocol + + p = listenTCP6(6666, TrivialServerFactory()) + c = connectTCP6('::1', 6666, TrivialClientFactory()) + + reactor.run() + +if __name__ == '__main__': + main() + -- cgit v1.2.3 From 0190ceb88992acf6b1e3d8cd6cb29c45b4b78470 Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Wed, 26 May 2010 16:17:11 +0200 Subject: Replaced IPv6 resolver. --- ipv6.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ipv6.py b/ipv6.py index eb6ce2e..12562c9 100644 --- a/ipv6.py +++ b/ipv6.py @@ -5,6 +5,9 @@ from twisted.internet import default from twisted.internet import protocol from twisted.internet import reactor +from twisted.names.client import Resolver +resolver = Resolver('/etc/resolv.conf') + class IPv6Address(object): def __init__(self, type, host, port, flowInfo, scope): self.type = type @@ -38,10 +41,17 @@ class Client(tcp.Client): if isIPv6Address(self.addr[0]): self._setRealAddress(self.addr[0]) else: - reactor.resolve(self.addr[0]).addCallbacks( - self._setRealAddress, self.failIfNotConnected + resolver.lookupIPV6Address(self.addr[0]).addCallbacks( + self.resolvedAddress, self.failIfNotConnected ) + def resolvedAddress(self, addr): + aaaa = addr[0][-1].payload + if aaaa.fancybasename != 'AAAA': + self.failIfNotConnected(Exception('Unable to resolve IPv6 address.')) + return + self._setRealAddress(aaaa._address) + def getHost(self): return IPv6Address('TCP', *self.socket.getsockname()) -- cgit v1.2.3 From dd71b25a6e82d523e9c841428b43d5270d0435af Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Wed, 26 May 2010 16:39:29 +0200 Subject: Better check for IPv6 addresses. --- ipv6.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ipv6.py b/ipv6.py index 12562c9..9dd1f32 100644 --- a/ipv6.py +++ b/ipv6.py @@ -46,10 +46,11 @@ class Client(tcp.Client): ) def resolvedAddress(self, addr): - aaaa = addr[0][-1].payload - if aaaa.fancybasename != 'AAAA': + aaaas = [x for x in addr[0] if x.type == 28] # 28 = AAAA record + if not len(aaaas): self.failIfNotConnected(Exception('Unable to resolve IPv6 address.')) return + aaaa = aaaas[0].payload self._setRealAddress(aaaa._address) def getHost(self): -- cgit v1.2.3