U
    P|jÕ1  ã                   @   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ZddlmZ ddl	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mZ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$m%Z% dddgZ&dZ'e (¡ dk�se (¡  )d¡�se (¡  )d¡�r"dZ*dZ+ndZ*dZ+dZ,G dd„ deƒZ-eej.ƒG dd„ de%e$ƒƒZ/G dd„ deddƒƒZ0G dd „ d eƒZ1G d!d"„ d"ƒZ2eej3ƒG d#d„ dej4ƒƒZ5dS )$zc
Support for Linux ethernet and IP tunnel devices.

@see: U{https://en.wikipedia.org/wiki/TUN/TAP}
é    N)Ú
namedtuple)ÚTuple)Ú	AttributeÚ	InterfaceÚimplementer)ÚFlagConstantÚFlags)ÚVersion)ÚabstractÚdeferÚerrorÚ
interfacesÚtask)ÚethernetÚraw)Úlog)Ú
deprecated)ÚfullyQualifiedName)ÚFancyEqMixinÚFancyStrMixinÚTunnelFlagsÚTunnelAddressÚ
TuntapPorté   ZpariscÚppcZsparcl   ÊT  iÒT@iÊT@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)   ú7/tmp/pip-unpacked-wheel-audpp6lv/twisted/pair/tuntap.pyr   6   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>^   ó    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+   `   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,   )r4   r-   r,   r)   r)   r*   Ú__init__i   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,   )r4   Úindexr)   r)   r*   Ú__getitem__t   s    üzTunnelAddress.__getitem__N)
r"   r#   r$   r%   ZcompareAttributesZshowAttributesÚpropertyr+   r5   r<   r)   r)   r)   r*   r   W   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   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)   )ÚfdÚoptÚargZmutate_flagr)   r)   r*   Úioctlœ   s    z_IInputOutputSystem.ioctlc                 C   s   dS )z"
        @see: L{os.read}
        Nr)   )rD   Úlimitr)   r)   r*   Úread¡   s    z_IInputOutputSystem.readc                 C   s   dS )z#
        @see: L{os.write}
        Nr)   )rD   Údatar)   r)   r*   Úwrite¦   s    z_IInputOutputSystem.writec                 C   s   dS )z#
        @see: L{os.close}
        Nr)   )rD   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)   )ÚdatagramÚ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)   )ÚfilenoÚhostÚportr)   r)   r*   Ú
receiveUDP¾   s    z_IInputOutputSystem.receiveUDP)r@   )NN)r"   r#   r$   r%   r   ÚO_RDWRÚ
O_NONBLOCKÚ	O_CLOEXECrC   rG   rI   rK   rL   rO   rS   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}.
    rV   i   N)r"   r#   r$   r%   ÚstaticmethodÚosrC   rI   rK   rL   ÚfcntlrG   rT   rU   ÚgetattrrV   r)   r)   r)   r*   rW   Ó   s   




rW   c                   @   s¢   e Zd ZdZdZd%dd„Ze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eeddddƒeƒ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› d�| _d S )Nr   r   z (ú))r   ZIEthernetProtocolZ
providedByr   r'   Ú_moder&   r   ZIRawPacketProtocolÚAssertionErrorrW   Ú_systemr
   ÚFileDescriptorr5   Ú	interfaceÚprotocolÚmaxPacketSizeZ_getLogPrefixr,   Úlogstr)r4   ra   Úprotorc   ÚreactorÚsystemÚ	logPrefixr)   r)   r*   r5   î   s    
zTuntapPort.__init__)Úreturnc                 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   rb   Ú	__class__Ú	connectedr]   r,   ra   )r4   Ú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)Ú_bindSocketrb   ZmakeConnectionZstartReadingr3   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ó    )r_   rT   rV   rU   ÚstructÚpackÚ	_IFNAMSIZr2   rC   Ú_TUN_KO_PATHrG   Ú
_TUNSETIFFr>   Ústrip)r4   r,   rB   ÚflagsÚconfigrP   Úresultr)   r)   r*   Ú_openTunnel  s
    zTuntapPort._openTunnelc              
   C   s~   t jd| jj| jd� z|  | j| jtjB ¡\}}W n2 t	k
rf } 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)Úformatrb   ra   Nr   )r   Úmsgrb   rk   ra   r{   r]   r   r(   ÚOSErrorr   ZCannotListenErrorÚ_filenorl   )r4   rP   ra   Úer)   r)   r*   ro   )  s    ý 
ÿ"zTuntapPort._bindSocketc                 C   s   | j S r.   )r   r3   r)   r)   r*   rP   >  s    zTuntapPort.filenoc              
   C   sÚ   d}|| j k rÖz| j | j| j¡}W nX tk
rh } z&|jtjtjtj	fkrVW Y ¢
dS ‚ W 5 d}~X Y n t
k
r|   ‚ Y nX |t|ƒ7 }z| jj|dd� W q t
k
rÒ   t| jjƒ}t dd|› d�¡ Y qX qdS )z=
        Called when my socket is ready for reading.
        r   N)ÚpartialzUnhandled exception from z.datagramReceived)ÚmaxThroughputr_   rI   r   rc   r~   ÚerrnoÚEWOULDBLOCKÚEAGAINÚEINTRÚBaseExceptionÚlenrb   ZdatagramReceivedr   rk   r   Úerr)r4   rI   rJ   r€   Úclsr)   r)   r*   ÚdoReadA  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)r_   rK   r   r~   rƒ   r†   )r4   rM   r€   r)   r)   r*   rK   X  s    zTuntapPort.writec                 C   s   |   d |¡¡ dS )zÒ
        Write a datagram constructed from a L{list} of L{bytes}.

        @param seq: The data that will make up the complete datagram to be
            written.
        @type seq: L{list} of L{bytes}
        r1   N)rK   Újoin)r4   Úseqr)   r)   r*   ÚwriteSequenceg  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_stoppedDeferredrl   r   Z
deferLaterrf   ÚconnectionLostr   Zsucceedr3   r)   r)   r*   ÚstopListeningq  s      ÿzTuntapPort.stopListeningZTwistedé   r   c                 C   s   |   ¡  tj¡ dS )zN
        Close this tunnel.  Use L{TuntapPort.stopListening} instead.
        N)r�   Z
addErrbackr   r‰   r3   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   r}   ra   r
   r`   r�   rb   ZdoStoprl   r_   rL   r   )r4   Úreasonr)   r)   r*   r�   Œ  s    
zTuntapPort.connectionLostc                 C   s   | j S )zK
        Returns the name of my class, to prefix log entries with.
        )rd   r3   r)   r)   r*   rh   ™  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   r]   ra   r3   r)   r)   r*   ÚgetHostŸ  s    zTuntapPort.getHost)r!   NN)N)r"   r#   r$   r%   r‚   r5   Ústrrn   rp   r{   ro   rP   r‹   rK   rŽ   r�   r   r	   r’   r�   rh   r•   r)   r)   r)   r*   r   æ   s"   
	


)6r%   rƒ   rZ   rY   Úplatformrr   r8   Úcollectionsr   Útypingr   Zzope.interfacer   r   r   Z
constantlyr   r   Úincrementalr	   Ztwisted.internetr
   r   r   r   r   Ztwisted.pairr   r   Ztwisted.pythonr   Ztwisted.python.deprecater   Ztwisted.python.reflectr   Ztwisted.python.utilr   r   Ú__all__rt   ÚmachineÚ
startswithrv   Z
_TUNGETIFFru   r   ZIAddressr   r>   r?   rW   ZIListeningPortr`   r   r)   r)   r)   r*   Ú<module>   sR   ý
ÿþý!)F