Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

modified pytap.py

By: a guest on Apr 25th, 2011  |  syntax: Python  |  size: 5.65 KB  |  views: 585  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. '''
  2. PyTap module that wraps the Linux TUN/TAP device
  3.  
  4. @author: Dominik George
  5. '''
  6.  
  7. # StB, 2.4.2011: Added method "fileno()", so we can use select.select().
  8.  
  9. from fcntl import ioctl
  10. import os
  11. import struct
  12. import atexit
  13.  
  14. TUNSETIFF = 0x400454ca
  15. IFF_TUN   = 0x0001
  16. IFF_TAP   = 0x0002
  17.  
  18. DEFAULT_MTU = 1500
  19. # StB, 25.4.2011: MTU=1500 means an Ethernet frame size of 1518 Bytes! (with VLAN its max. 1522 Bytes) We need to increase the read buffer in the "read()" method. AFAIK Linux don't use VLAN as default.
  20. # http://de.wikipedia.org/wiki/Maximum_Transmission_Unit#Beispiel_Ethernet
  21. # http://de.wikipedia.org/w/index.php?title=Datei:Ethernetpaket.svg&filetimestamp=20090225134531
  22. ETHERNET_HEADER_SIZE = 18
  23.  
  24.  
  25. class TapDevice:
  26.     ''' TUN/TAP device object '''
  27.  
  28.     def __init__(self, mode = IFF_TUN, name = '', dev = '/dev/net/tun'):
  29.         '''
  30.        Initialize TUN/TAP device object
  31.  
  32.        mode is either IFF_TUN or IFF_TAP to select tun or tap device mode.
  33.  
  34.        name is the name of the new device. An integer will be added to
  35.        build the real device name.
  36.  
  37.        dev is the device node name the control channel is connected to.
  38.        '''
  39.  
  40.         # Set interface mdoe in object
  41.         self.mode = mode
  42.  
  43.         # Create interface name to request from tuntap module
  44.         if name == '':
  45.             if self.mode == IFF_TUN:
  46.                 self.name = 'tun%d'
  47.             elif self.mode == IFF_TAP:
  48.                 self.name = 'tap%d'
  49.         elif name.endswith('%d'):
  50.             self.name = name
  51.         else:
  52.             self.name = name + '%d'
  53.        
  54.         # Open control device and request interface
  55.         fd = os.open(dev, os.O_RDWR)
  56.         ifs = ioctl(fd, TUNSETIFF, struct.pack("16sH", self.name, self.mode))
  57.        
  58.         # Retreive real interface name from control device
  59.         self.name = ifs[:16].strip("\x00")
  60.        
  61.         # Set default MTU
  62.         self.mtu = DEFAULT_MTU
  63.        
  64.         # Store fd for later
  65.         self.__fd__ = fd
  66.        
  67.         # Properly close device on exit
  68.         atexit.register(self.close)
  69.    
  70.  
  71.     def fileno(self):
  72.         return self.__fd__    
  73.  
  74.    
  75.     def read(self):
  76.         '''
  77.        Read data from the device. The device mtu determines how many bytes
  78.        will be read.
  79.  
  80.        The data read from the device is returned in its raw form.
  81.        '''
  82.  
  83.         data = os.read(self.__fd__, self.mtu + ETHERNET_HEADER_SIZE)
  84.         return data
  85.    
  86.     def write(self, data):
  87.         '''
  88.        Write data to the device. No care is taken for MTU limitations or similar.
  89.        '''
  90.  
  91.         os.write(self.__fd__, data)
  92.        
  93.     def ifconfig(self, **args):
  94.         '''
  95.        Issue ifconfig command on the device. The method takes the following
  96.        keyword arguments:
  97.  
  98.         address   => IP address of the device, can be in CIDR notation (see man ifconfig)
  99.         netmask   => Network mask
  100.         network   => Network base address, normally set automatically
  101.         broadcast => Broadcast address, normally set automatically
  102.         mtu       => Link MTU, this will also affect the read() method
  103.         hwclass   => Hardware class, normally ether for ethernet
  104.         hwaddress => Hardware (MAC) address, in conjunction with hwclass
  105.        '''
  106.        
  107.         ifconfig = 'ifconfig ' + self.name + ' '
  108.        
  109.         # IP address ?
  110.         try:
  111.             ifconfig = ifconfig + args['address'] + ' '
  112.         except KeyError:
  113.             pass
  114.        
  115.         # Network mask ?
  116.         try:
  117.             ifconfig = ifconfig + 'netmask ' + args['netmask'] + ' '
  118.         except KeyError:
  119.             pass
  120.        
  121.         # Network base address ?
  122.         try:
  123.             ifconfig = ifconfig + 'network ' + args['network'] + ' '
  124.         except KeyError:
  125.             pass
  126.        
  127.         # Broadcast address ?
  128.         try:
  129.             ifconfig = ifconfig + 'broadcast ' + args['broadcast'] + ' '
  130.         except KeyError:
  131.             pass
  132.        
  133.         # MTU ?
  134.         try:
  135.             ifconfig = ifconfig + 'mtu ' + str(args['mtu']) + ' '
  136.         except KeyError:
  137.             pass
  138.        
  139.         # Hardware address ?
  140.         try:
  141.             ifconfig = ifconfig + 'hw ' + args['hwclass'] + ' ' + args['hwaddress'] + ' '
  142.         except KeyError:
  143.             pass
  144.        
  145.         # Try to set off ifconfig command
  146.         ret = os.system(ifconfig)
  147.        
  148.         if ret != 0:
  149.             raise IfconfigError()
  150.        
  151.         # Save MTU if ifconfig was successful so buffer sizes can be adjusted
  152.         try:
  153.             self.mtu = args['mtu']
  154.         except KeyError:
  155.             pass
  156.  
  157.     def up(self):
  158.         '''
  159.        Bring up device. This will effectively run "ifconfig up" on the device.
  160.        '''
  161.  
  162.         ret = os.system("ifconfig " + self.name + " up")
  163.        
  164.         if ret != 0:
  165.             raise IfconfigError()
  166.        
  167.     def down(self):
  168.         '''
  169.        Bring down device. This will effectively call "ifconfig down" on the device.
  170.        '''
  171.  
  172.         ret = os.system("ifconfig " + self.name + " down")
  173.        
  174.         if ret != 0:
  175.             raise IfconfigError()
  176.        
  177.     def close(self):
  178.         '''
  179.        Close the control channel. This will effectively drop all locks and remove the
  180.        TUN/TAP device.
  181.  
  182.        You must manually take care that your code does not try to operate on the interface
  183.        after closing the control channel.
  184.        '''
  185.  
  186.         os.close(self.__fd__)
  187.  
  188.        
  189. class IfconfigError(Exception):
  190.     ''' Exception thrown if an ifconfig command returns with a non-zero exit status. '''
  191.  
  192.     pass