Tunnel ethernet over EVERYTHING!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ether2any.py 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. # -*- coding: utf-8 -*-
  2. import commands
  3. import select
  4. import pytap
  5. import logging
  6. from pytap import TapDevice
  7. class Ether2Any:
  8. """ Baseclass for writing arbitrary Ethernet/IP tunnel using a TUN/TAP device.
  9. This class handles a TUN/TAP devices and runs a select loop for it and,
  10. if given, a set of sockets. To use this class at least sendToNet() has
  11. to be implemented by a subclass. """
  12. def __init__(self, tap=True, readSockets=[]):
  13. """ Constructor for Ether2Any.
  14. isTap defines if the managed device should be a tap (ethernet tunnel)
  15. or a tun (IP tunnel). """
  16. self.readSockets = readSockets
  17. # create device
  18. self.dev = TapDevice(tap=tap)
  19. self.timeout = None
  20. def setupLogging(self, name):
  21. l = logging.getLogger(name)
  22. fmt = logging.Formatter("%(asctime)s - [%(levelname)s] (%(name)s) - %(message)s")
  23. ch = logging.StreamHandler()
  24. ch.setFormatter(fmt)
  25. l.addHandler(ch)
  26. return l
  27. def addSocket(self, sock):
  28. """ Add socket to readSockets set. """
  29. self.readSockets.append(sock)
  30. def delSocket(self, socket):
  31. """ Remove socket from readSockets set. """
  32. try:
  33. self.readSockets.remove(socket)
  34. except ValueError:
  35. pass
  36. # outgoing data
  37. def sendToNet(self, packet):
  38. """ This function has to be implemented to handle outgoing
  39. data (read from the TUN/TAP device) """
  40. raise NotImplementedError("You need to overload sendToNet()")
  41. # incoming data
  42. def sendToDev(self, sock):
  43. """ This function has to be implemented to handle incoming
  44. data which is read from the extra sockets (self.readSockets).
  45. It will not be called when no extra readSockets are specified. """
  46. raise NotImplementedError("You need to overload sendToDev()")
  47. def setTimeout(self, t):
  48. """ Set select timeout. """
  49. self.timeout = t
  50. def callAfterSelect(self):
  51. """ Will be called as last operation of the mainloop when
  52. handling of the select result / the select timeout is hit.
  53. """
  54. pass
  55. def run(self):
  56. """ Run main select-loop. """
  57. try:
  58. while True:
  59. sockets = [self.dev.getFD()] + self.readSockets
  60. (readFDs, _, _) = select.select(sockets, [], [], self.timeout)
  61. for readFD in readFDs:
  62. if readFD == self.dev.getFD():
  63. self.sendToNet(self.dev.read())
  64. elif readFD in self.readSockets:
  65. self.sendToDev(readFD)
  66. self.callAfterSelect()
  67. except KeyboardInterrupt:
  68. self.quit()
  69. self.dev.close()
  70. def quit(self):
  71. """ Will be called after the run-select() and its processing is done. """
  72. pass