U
    W[0                     @   s  d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z	m
Z
 ddlmZmZmZ ddlmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZmZmZmZ ddl m!Z!m"Z" dddgZ#dZ$dZ%dZ&dZ'G dd de	Z(eej)G dd deee*Z+G dd deddZ,G dd deZ-G dd de*Z.eej/G dd dej0Z1eedddde1j2e1j3e1_3dS ) zc
Support for Linux ethernet and IP tunnel devices.

@see: U{https://en.wikipedia.org/wiki/TUN/TAP}
    N)
namedtuple)FlagsFlagConstant)	Attribute	Interfaceimplementer)FancyEqMixinFancyStrMixin)Version)fullyQualifiedName)
deprecated)log)abstracterrortask
interfacesdefer)ethernetrawTunnelFlagsTunnelAddress
TuntapPort   iT@l   T  s   /dev/net/tunc                   @   sp   e Zd ZdZedZedZedZedZedZ	edZ
edZed	Zed
ZedZedZedZdS )r   a~  
    L{TunnelFlags} defines more flags which are used to configure the behavior
    of a tunnel device.

    @cvar IFF_TUN: This indicates a I{tun}-type device.  This type of tunnel
        carries IP datagrams.  This flag is mutually exclusive with C{IFF_TAP}.

    @cvar IFF_TAP: This indicates a I{tap}-type device.  This type of tunnel
        carries ethernet frames.  This flag is mutually exclusive with C{IFF_TUN}.

    @cvar IFF_NO_PI: This indicates the I{protocol information} header will
        B{not} be included in data read from the tunnel.

    @see: U{https://www.kernel.org/doc/Documentation/networking/tuntap.txt}
          r       @         i   i       i @  i   N)__name__
__module____qualname____doc__r   IFF_TUNIFF_TAPZ
TUN_FASYNCZTUN_NOCHECKSUMZ	TUN_NO_PIZTUN_ONE_QUEUEZTUN_PERSISTZTUN_VNET_HDR	IFF_NO_PIZIFF_ONE_QUEUEZIFF_VNET_HDRZIFF_TUN_EXCL r'   r'   5/usr/lib/python3/dist-packages/twisted/pair/tuntap.pyr   (   s   c                   @   s@   e Zd ZdZdZddd fdfZedd Zd	d
 Zdd Z	dS )r   zU
    A L{TunnelAddress} represents the tunnel to which a L{TuntapPort} is bound.
    )
_typeValuenametypec                 C   s   | j S N)r*   )flagr'   r'   r(   <lambda>O       zTunnelAddress.<lambda>r*   c                 C   s   | j jS )z
        Return the integer value of the C{type} attribute.  Used to produce
        correct results in the equality implementation.
        )r+   valueselfr'   r'   r(   r)   Q   s    zTunnelAddress._typeValuec                 C   s   || _ || _dS )z
        @param type: Either L{TunnelFlags.IFF_TUN} or L{TunnelFlags.IFF_TAP},
            representing the type of this tunnel.

        @param name: The system name of the tunnel.
        @type name: L{bytes}
        N)r+   r*   )r2   r+   r*   r'   r'   r(   __init__[   s    zTunnelAddress.__init__c                 C   s   t jdtdd d| jf| S )zS
        Deprecated accessor for the tunnel name.  Use attributes instead.
        zUTunnelAddress.__getitem__ is deprecated since Twisted 14.0.0  Use attributes instead.r   )category
stacklevelZTUNTAP)warningswarnDeprecationWarningr*   )r2   indexr'   r'   r(   __getitem__g   s    zTunnelAddress.__getitem__N)
r    r!   r"   r#   ZcompareAttributesZshowAttributespropertyr)   r3   r:   r'   r'   r'   r(   r   I   s   
	c                   @   s   e Zd ZdZdS )_TunnelDescriptionz
    Describe an existing tunnel.

    @ivar fileno: the file descriptor associated with the tunnel
    @type fileno: L{int}

    @ivar name: the name of the tunnel
    @type name: L{bytes}
    N)r    r!   r"   r#   r'   r'   r'   r(   r<   s   s   r<   zfileno namec                   @   sd   e Zd ZdZedZedZedZdddZdd	d
Z	dd Z
dd Zdd Zdd Zdd ZdS )_IInputOutputSystemz
    An interface for performing some basic kinds of I/O (particularly that I/O
    which might be useful for L{twisted.pair.tuntap}-using code).
    z@see: L{os.O_RDWR}z@see: L{os.O_NONBLOCK}z@see: L{os.O_CLOEXEC}  c                 C   s   dS )z"
        @see: L{os.open}
        Nr'   )filenamer-   moder'   r'   r(   open   s    z_IInputOutputSystem.openNc                 C   s   dS )z&
        @see: L{fcntl.ioctl}
        Nr'   )fdZoptargZmutate_flagr'   r'   r(   ioctl   s    z_IInputOutputSystem.ioctlc                 C   s   dS )z"
        @see: L{os.read}
        Nr'   )rB   limitr'   r'   r(   read   s    z_IInputOutputSystem.readc                 C   s   dS )z#
        @see: L{os.write}
        Nr'   )rB   datar'   r'   r(   write   s    z_IInputOutputSystem.writec                 C   s   dS )z#
        @see: L{os.close}
        Nr'   )rB   r'   r'   r(   close   s    z_IInputOutputSystem.closec                 C   s   dS )a  
        Send a datagram to a certain address.

        @param datagram: The payload of a UDP datagram to send.
        @type datagram: L{bytes}

        @param address: The destination to which to send the datagram.
        @type address: L{tuple} of (L{bytes}, L{int})

        @return: The local address from which the datagram was sent.
        @rtype: L{tuple} of (L{bytes}, L{int})
        Nr'   )datagramZaddressr'   r'   r(   sendUDP   s    z_IInputOutputSystem.sendUDPc                 C   s   dS )af  
        Return a socket which can be used to receive datagrams sent to the
        given address.

        @param fileno: A file descriptor representing a tunnel device which the
            datagram was either sent via or will be received via.
        @type fileno: L{int}

        @param host: The IPv4 address at which the datagram will be received.
        @type host: L{bytes}

        @param port: The UDP port number at which the datagram will be
            received.
        @type port: L{int}

        @return: A L{socket.socket} which can be used to receive the specified
            datagram.
        Nr'   )filenoZhostZportr'   r'   r(   
receiveUDP   s    z_IInputOutputSystem.receiveUDP)r>   )NN)r    r!   r"   r#   r   O_RDWR
O_NONBLOCK	O_CLOEXECrA   rD   rF   rH   rI   rK   rM   r'   r'   r'   r(   r=      s   

r=   c                   @   sZ   e Zd ZdZeejZeejZeejZeej	Z	ee
jZejZejZeeddZdS )_RealSystemz
    An interface to the parts of the operating system which L{TuntapPort}
    relies on.  This is most of an implementation of L{_IInputOutputSystem}.
    rP   i   N)r    r!   r"   r#   staticmethodosrA   rF   rH   rI   fcntlrD   rN   rO   getattrrP   r'   r'   r'   r(   rQ      s   




rQ   c                   @   s   e Zd ZdZdZd!ddZdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zd"ddZdd Zdd  ZdS )#r   zH
    A Port that reads and writes packets from/to a TUN/TAP-device.
    i   r   Nc                 C   s   t j|rd| _ tj| _nd| _ tj| _tj|s:t	|d krHt
 }|| _tj| | || _|| _|| _| | j}d|| jjf | _d S )Nr   r   z%s (%s))r   ZIEthernetProtocolZ
providedByr   r%   _moder$   r   ZIRawPacketProtocolAssertionErrorrQ   _systemr   FileDescriptorr3   	interfaceprotocolmaxPacketSizeZ_getLogPrefixr*   logstr)r2   rZ   protor\   reactorsystem	logPrefixr'   r'   r(   r3      s    
zTuntapPort.__init__c                 C   s@   t | jjf}| jr|d }n|d }|| jj| jf }d| S )N) )znot z<%s %slistening on %s/%s>)r   r[   	__class__	connectedrV   r*   rZ   )r2   argsr'   r'   r(   __repr__   s    
zTuntapPort.__repr__c                 C   s    |    | j|  |   dS )z
        Create and bind my socket, and begin listening on it.

        This must be called after creating a server to begin listening on the
        specified tunnel.
        N)_bindSocketr[   ZmakeConnectionZstartReadingr1   r'   r'   r(   startListening  s    zTuntapPort.startListeningc                 C   sd   | j j| j jB | j jB }tdtf ||j}| j t	|}| j 
|t|}t||dt dS )af  
        Open the named tunnel using the given mode.

        @param name: The name of the tunnel to open.
        @type name: L{bytes}

        @param mode: Flags from L{TunnelFlags} with exactly one of
            L{TunnelFlags.IFF_TUN} or L{TunnelFlags.IFF_TAP} set.

        @return: A L{_TunnelDescription} representing the newly opened tunnel.
        z%dsHN    )rX   rN   rP   rO   structZpack	_IFNAMSIZr0   rA   _TUN_KO_PATHrD   
_TUNSETIFFr<   strip)r2   r*   r@   flagsZconfigrL   resultr'   r'   r(   _openTunnel  s    zTuntapPort._openTunnelc              
   C   s   t jd| jj| jd z| | j| jtjB \}}W n6 t	t
fk
rj } ztd| j|W 5 d}~X Y nX || _|| _d| _dS )z"
        Open the tunnel.
        z&%(protocol)s starting on %(interface)s)formatr[   rZ   Nr   )r   msgr[   rc   rZ   rq   rV   r   r&   IOErrorOSErrorr   ZCannotListenError_filenord   )r2   rL   rZ   er'   r'   r(   rg   (  s     
"zTuntapPort._bindSocketc                 C   s   | j S r,   )rv   r1   r'   r'   r(   rL   <  s    zTuntapPort.filenoc              
   C   s   d}|| j k rz| j| j| j}W nP tk
rh } z&|jtjtjtj	fkrVW Y 
dS  W 5 d}~X Y n    Y nX |t
|7 }z| jj|dd W q   t| jj}tdd|f  Y qX qdS )z=
        Called when my socket is ready for reading.
        r   N)partialz,Unhandled exception from %s.datagramReceived)maxThroughputrX   rF   rv   r\   EnvironmentErrorerrnoZEWOULDBLOCKZEAGAINEINTRlenr[   ZdatagramReceivedr   rc   r   err)r2   rF   rG   rw   clsr'   r'   r(   doRead@  s&    

zTuntapPort.doReadc              
   C   sZ   z| j | j|W S  tk
rT } z$|jtjkrB| | W Y S  W 5 d}~X Y nX dS )z
        Write the given data as a single datagram.

        @param datagram: The data that will make up the complete datagram to be
            written.
        @type datagram: L{bytes}
        N)rX   rH   rv   rt   r{   r|   )r2   rJ   rw   r'   r'   r(   rH   Z  s    zTuntapPort.writec                 C   s   |  d| dS )z
        Write a datagram constructed from a L{list} of L{bytes}.

        @param datagram: The data that will make up the complete datagram to be
            written.
        @type seq: L{list} of L{bytes}
        r/   N)rH   join)r2   seqr'   r'   r(   writeSequencej  s    zTuntapPort.writeSequencec                 C   sH   |    | jr| jS | jr:t| jd| j| _d| _| jS t	dS dS )z
        Stop accepting connections on this port.

        This will shut down my socket and call self.connectionLost().

        @return: A L{Deferred} that fires when this port has stopped.
        r   TN)
ZstopReadingZdisconnectingZ_stoppedDeferredrd   r   Z
deferLaterr_   connectionLostr   Zsucceedr1   r'   r'   r(   stopListeningu  s      zTuntapPort.stopListeningc                 C   s   |   tj dS )zN
        Close this tunnel.  Use L{TuntapPort.stopListening} instead.
        N)r   Z
addErrbackr   r~   r1   r'   r'   r(   loseConnection  s    zTuntapPort.loseConnectionc                 C   sF   t d| j  tj| | | j  d| _| j	
| j d| _dS )zY
        Cleans up my socket.

        @param reason: Ignored.  Do not use this.
        z(Tuntap %s Closed)r   N)r   rs   rZ   r   rY   r   r[   ZdoStoprd   rX   rI   rv   )r2   reasonr'   r'   r(   r     s    
zTuntapPort.connectionLostc                 C   s   | j S )zK
        Returns the name of my class, to prefix log entries with.
        )r]   r1   r'   r'   r(   ra     s    zTuntapPort.logPrefixc                 C   s   t | j| jS )z
        Get the local address of this L{TuntapPort}.

        @return: A L{TunnelAddress} which describes the tunnel device to which
            this object is bound.
        @rtype: L{TunnelAddress}
        )r   rV   rZ   r1   r'   r'   r(   getHost  s    zTuntapPort.getHost)r   NN)N)r    r!   r"   r#   ry   r3   rf   rh   rq   rg   rL   r   rH   r   r   r   r   ra   r   r'   r'   r'   r(   r      s$     


ZTwisted   )4r#   rS   rT   r{   rj   r6   collectionsr   Z
constantlyr   r   Zzope.interfacer   r   r   Ztwisted.python.utilr   r	   Zincrementalr
   Ztwisted.python.reflectr   Ztwisted.python.deprecater   Ztwisted.pythonr   Ztwisted.internetr   r   r   r   r   Ztwisted.pairr   r   __all__rk   rm   Z
_TUNGETIFFrl   r   ZIAddressobjectr   r<   r=   rQ   ZIListeningPortrY   r   r   r   r'   r'   r'   r(   <module>   sL     !)L P