o
    b0                     @   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   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_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