o
    ¯b¹0  ã                   @   sl  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	 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$ g d¢Z%dZ&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ƒƒZ-G dd„ deƒZ.G dd„ dƒZ/eej0ƒG dd„ dej1ƒƒZ2d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é   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_TAPÚ
TUN_FASYNCÚTUN_NOCHECKSUMÚ	TUN_NO_PIÚTUN_ONE_QUEUEÚTUN_PERSISTÚTUN_VNET_HDRÚ	IFF_NO_PIÚIFF_ONE_QUEUEÚIFF_VNET_HDRÚIFF_TUN_EXCL© r1   r1   ú5/usr/lib/python3/dist-packages/twisted/pair/tuntap.pyr   ,   s    r   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   ó   | j S ©N)r4   )Úflagr1   r1   r2   Ú<lambda>T   s    zTunnelAddress.<lambda>r4   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.
        )r5   Úvalue©Úselfr1   r1   r2   r3   V   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)r5   r4   )r<   r5   r4   r1   r1   r2   Ú__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Ú
stacklevelÚTUNTAP)ÚwarningsÚwarnÚDeprecationWarningr4   )r<   Úindexr1   r1   r2   Ú__getitem__j   s   üzTunnelAddress.__getitem__N)
r!   r"   r#   r$   ÚcompareAttributesÚshowAttributesÚpropertyr3   r=   rE   r1   r1   r1   r2   r   M   s    
r   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$   r1   r1   r1   r2   rI   w   s    rI   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   ó   dS )z"
        @see: L{os.open}
        Nr1   )Úfilenamer8   Úmoder1   r1   r2   Úopen�   ó    z_IInputOutputSystem.openNc                 C   rL   )z&
        @see: L{fcntl.ioctl}
        Nr1   )ÚfdÚoptÚargÚmutate_flagr1   r1   r2   Úioctl’   rP   z_IInputOutputSystem.ioctlc                 C   rL   )z"
        @see: L{os.read}
        Nr1   )rQ   Úlimitr1   r1   r2   Úread—   rP   z_IInputOutputSystem.readc                 C   rL   )z#
        @see: L{os.write}
        Nr1   )rQ   Údatar1   r1   r2   Úwriteœ   rP   z_IInputOutputSystem.writec                 C   rL   )z#
        @see: L{os.close}
        Nr1   )rQ   r1   r1   r2   Úclose¡   rP   z_IInputOutputSystem.closec                 C   rL   )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})
        Nr1   )ÚdatagramÚaddressr1   r1   r2   ÚsendUDP¦   rP   z_IInputOutputSystem.sendUDPc                 C   rL   )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.
        Nr1   )ÚfilenoÚhostÚportr1   r1   r2   Ú
receiveUDP´   rP   z_IInputOutputSystem.receiveUDP)rK   )NN)r!   r"   r#   r$   r   ÚO_RDWRÚ
O_NONBLOCKÚ	O_CLOEXECrO   rU   rW   rY   rZ   r]   ra   r1   r1   r1   r2   rJ   ƒ   s    

rJ   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}.
    rd   i   N)r!   r"   r#   r$   ÚstaticmethodÚosrO   rW   rY   rZ   ÚfcntlrU   rb   rc   Úgetattrrd   r1   r1   r1   r2   re   É   s    




re   c                   @   s¢   e Zd ZdZdZd%dd„Zdef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J ‚|d u r$t	ƒ }|| _
tj | |¡ || _|| _|| _|  | j¡}|› d| jj› d�| _d S )Nr   r   z (ú))r   ÚIEthernetProtocolÚ
providedByr   r&   Ú_moder%   r   ÚIRawPacketProtocolre   Ú_systemr
   ÚFileDescriptorr=   Ú	interfaceÚprotocolÚmaxPacketSizeÚ_getLogPrefixr4   Úlogstr)r<   rq   Úprotors   ÚreactorÚsystemÚ	logPrefixr1   r1   r2   r=   ä   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   rr   Ú	__class__Ú	connectedrm   r4   rq   )r<   Úargsr1   r1   r2   Ú__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)Ú_bindSocketrr   ÚmakeConnectionÚstartReadingr;   r1   r1   r2   Ú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ó    )ro   rb   rd   rc   ÚstructÚpackÚ	_IFNAMSIZr:   rO   Ú_TUN_KO_PATHrU   Ú
_TUNSETIFFrI   Ústrip)r<   r4   rN   ÚflagsÚconfigr^   Úresultr1   r1   r2   Ú_openTunnel  s
   zTuntapPort._openTunnelc              
   C   st   t jd| jj| jd� z|  | j| jtjB ¡\}}W n t	y. } zt
 d| j|¡‚d}~ww || _|| _d| _dS )z"
        Open the tunnel.
        z&%(protocol)s starting on %(interface)s)Úformatrr   rq   Nr   )r   Úmsgrr   r|   rq   rŽ   rm   r   r-   ÚOSErrorr   ÚCannotListenErrorÚ_filenor}   )r<   r^   rq   Úer1   r1   r2   r€     s    ýÿ€ÿ
zTuntapPort._bindSocketc                 C   r6   r7   )r“   r;   r1   r1   r2   r^   4  s   zTuntapPort.filenoc              
   C   sØ   d}|| j k rjz| j | j| j¡}W n& ty1 } z|jtjtjtj	fv r,W Y d}~dS ‚ d}~w t
y8   ‚ w |t|ƒ7 }z
| jj|dd� W n t
yb   t| jjƒ}t dd|› d�¡ Y nw || j k sdS dS )z=
        Called when my socket is ready for reading.
        r   N)ÚpartialzUnhandled exception from z.datagramReceived)ÚmaxThroughputro   rW   r“   rs   r‘   ÚerrnoÚEWOULDBLOCKÚEAGAINÚEINTRÚBaseExceptionÚlenrr   ÚdatagramReceivedr   r|   r   Úerr)r<   rW   rX   r”   Úclsr1   r1   r2   ÚdoRead7  s(   
€ÿþòzTuntapPort.doReadc              
   C   sP   z	| j  | j|¡W S  ty' } z|jtjkr"|  |¡W  Y d}~S ‚ d}~ww )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)ro   rY   r“   r‘   r—   rš   )r<   r[   r”   r1   r1   r2   rY   N  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}
        ó    N)rY   Újoin)r<   Úseqr1   r1   r2   ÚwriteSequence]  s   zTuntapPort.writeSequencec                 C   sD   |   ¡  | jr
| jS | jrt | jd| j¡| _d| _| jS t 	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)
ÚstopReadingÚdisconnectingÚ_stoppedDeferredr}   r   Ú
deferLaterrw   ÚconnectionLostr   Úsucceedr;   r1   r1   r2   ÚstopListeningg  s   
ÿ
zTuntapPort.stopListeningÚTwistedé   r   c                 C   s   |   ¡  tj¡ dS )zN
        Close this tunnel.  Use L{TuntapPort.stopListening} instead.
        N)r«   Ú
addErrbackr   rž   r;   r1   r1   r2   Ú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�   rq   r
   rp   r©   rr   ÚdoStopr}   ro   rZ   r“   )r<   Úreasonr1   r1   r2   r©   ‚  s   

zTuntapPort.connectionLostc                 C   r6   )zK
        Returns the name of my class, to prefix log entries with.
        )ru   r;   r1   r1   r2   ry   �  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   rm   rq   r;   r1   r1   r2   ÚgetHost•  s   zTuntapPort.getHost)r    NNr7   )r!   r"   r#   r$   r–   r=   Ústrr   rƒ   rŽ   r€   r^   r    rY   r¤   r«   r   r	   r¯   r©   ry   r³   r1   r1   r1   r2   r   Ü   s$    
	


r   )3r$   r—   rh   rg   r…   rA   Úcollectionsr   Útypingr   Úzope.interfacer   r   r   Ú
constantlyr   r   Úincrementalr	   Útwisted.internetr
   r   r   r   r   Útwisted.pairr   r   Útwisted.pythonr   Útwisted.python.deprecater   Útwisted.python.reflectr   Útwisted.python.utilr   r   Ú__all__r‡   r‰   Ú
_TUNGETIFFrˆ   r   ÚIAddressr   rI   rJ   re   ÚIListeningPortrp   r   r1   r1   r1   r2   Ú<module>   s<   !)F