a
    kÄ#dr/  ã                   @   s¶   d dl Z d dlmZmZmZmZmZmZ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mZmZmZ d dlm  mZ G dd„ deƒZG d	d
„ d
eƒZG dd„ deƒZdS )é    N)ÚIterableÚOptionalÚUnionÚListÚTupleÚDictÚAnyÚType)ÚEDecimal)ÚPacket)ÚDefaultSession)ÚISOTPÚN_PCI_CFÚN_PCI_SFÚN_PCI_FFÚN_PCI_FCc                   @   s2   e Zd ZdZdgZdd„ Zdd„ Zdd„ ZeZd	S )
ÚISOTPMessageBuilderIterz0
    Iterator class for ISOTPMessageBuilder
    Úbuilderc                 C   s
   || _ d S ©N)r   )Úselfr   © r   úV/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/isotp/isotp_utils.pyÚ__init__   s    z ISOTPMessageBuilderIter.__init__c                 C   s   | S r   r   ©r   r   r   r   Ú__iter__!   s    z ISOTPMessageBuilderIter.__iter__c                 C   s,   | j jr$| j  ¡ }|d u rq$q |S q t‚d S r   )r   ÚcountÚpopÚStopIteration)r   Úpr   r   r   Ú__next__%   s    
z ISOTPMessageBuilderIter.__next__N)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úslotsr   r   r   Únextr   r   r   r   r      s   
r   c                   @   s–   e Zd ZdZG dd„ deƒZddefdd„Zdd„ Ze	d	d
„ ƒZ
dd„ Zddd„Zdd„ Zeefdd„ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚISOTPMessageBuilderaÛ  
    Initialize a ISOTPMessageBuilder object

    Utility class to build ISOTP messages out of CAN frames, used by both
    ISOTP.defragment() and ISOTPSession.

    This class attempts to interpret some CAN frames as ISOTP frames, both with
    and without extended addressing at the same time. For example, if an
    extended address of 07 is being used, all frames will also be interpreted
    as ISOTP single-frame messages.

    CAN frames are fed to an ISOTPMessageBuilder object with the feed() method
    and the resulting ISOTP frames can be extracted using the pop() method.

    :param use_ext_address: True for only attempting to defragment with
                         extended addressing, False for only attempting
                         to defragment without extended addressing,
                         or None for both
    :param rx_id: Destination Identifier
    :param basecls: The class of packets that will be returned,
                    defaults to ISOTP
    c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )zISOTPMessageBuilder.BucketzS
        Helper class to store not finished ISOTP messages while building.
        c                 C   s:   t ƒ | _|| _d| _d | _d | _d | _|| _|  |¡ d S ©Nr   )	ÚlistÚpiecesÚ	total_lenÚcurrent_lenÚreadyÚtx_idÚext_addressÚtimeÚpush)r   r*   Zfirst_pieceÚtsr   r   r   r   O   s    z#ISOTPMessageBuilder.Bucket.__init__c                 C   sd   | j  |¡ |  jt|ƒ7  _| j| jkr`tjr>d | j ¡}nd tt	| j ƒ¡}|d | j… | _
d S )Nó    Ú )r)   Úappendr+   Úlenr*   ÚsixÚPY3ÚjoinÚmapÚstrr,   )r   ZpieceÚ
isotp_datar   r   r   r0   Z   s    zISOTPMessageBuilder.Bucket.pushN)r    r!   r"   r#   r   r0   r   r   r   r   ÚBucketJ   s   r<   Nc                 C   sv   g | _ i | _|| _|| _d | _d | _d | _|d urrt|tƒrD|| _n.t|t	ƒrX|g| _nt
|dƒrj|| _ntdƒ‚d S )Nr   z Invalid type for argument rx_id!)r,   ÚbucketsÚuse_ext_addrÚbaseclsÚrx_idsÚlast_ffÚ
last_ff_exÚ
isinstancer(   ÚintÚhasattrÚ	TypeError)r   Úuse_ext_addressÚrx_idr?   r   r   r   r   e   s    



zISOTPMessageBuilder.__init__c                 C   sÊ   t |tƒs,t|dƒr,|D ]}|  |¡ qdS t |tƒs:dS | jdurT|j| jvrTdS t|jƒ}t|ƒdkrˆ| j	durˆ|  
|jd||j¡ t|ƒdkrÆ| j	durÆt |d¡}|  
|j||dd… |j¡ dS )z<Attempt to feed an incoming CAN frame into the state machiner   Né   Té   Fr   )rC   r   rE   Úfeedr@   Ú
identifierÚbytesÚdatar5   r>   Ú	_try_feedr/   r6   Ú
indexbytes)r   Zcanr   rN   Úear   r   r   rK   }   s    

zISOTPMessageBuilder.feedc                 C   s
   t | jƒS )z�Returns the number of ready ISOTP messages built from the provided
        can frames

        :return: Number of ready ISOTP messages
        )r5   r,   r   r   r   r   r   “   s    zISOTPMessageBuilder.countc                 C   s   | j S r   )r   r   r   r   r   Ú__len__�   s    zISOTPMessageBuilder.__len__c                 C   sŒ   |durdt t| jƒƒD ]H}| j| }|d }|d }||kr||krt | j |¡| j¡  S qdS t| jƒdkrˆt | j d¡| j¡S dS )ap  Returns a built ISOTP message

        :param identifier: if not None, only return isotp messages with this
                           destination
        :param ext_addr: if identifier is not None, only return isotp messages
                         with this extended address for destination
        :returns: an ISOTP packet, or None if no message is ready
        Nr   rI   )Úranger5   r,   r&   Ú_buildr   r?   )r   rL   Zext_addrÚiÚbZidenrQ   r   r   r   r   ¡   s    
ÿ
zISOTPMessageBuilder.popc                 C   s   t | ƒS r   )r   r   r   r   r   r   º   s    zISOTPMessageBuilder.__iter__c                 C   s|   | d }|j pd}||ƒ}t|dƒr.| d |_t|dƒrB| d |_t|dƒrT|j|_t|dƒrf|j|_t|d	ƒrx|j|_|S )
NrJ   r2   rH   r   Úrx_ext_addressrI   r-   r.   r/   )r,   rE   rH   rW   r-   r.   r/   )Útr?   ÚbucketrN   r   r   r   r   rT   ¾   s    







zISOTPMessageBuilder._buildc           	      C   s´   t |ƒdk rdS t dt|d d… ƒ¡d }|d@ }|dd … }|dkr|t |ƒdkr|t dt|dd… ƒ¡d }|dd … }||d	f}|d u r–|| _n|| _|  |||¡| j|< d
S )Né   Fz>HrJ   r   iÿ  é   z>IrI   T)r5   ÚstructÚunpackrM   rA   rB   r<   r=   )	r   rL   rQ   rN   r1   ÚheaderZexpected_lengthr;   Úkeyr   r   r   Ú_feed_first_frameÓ   s    
z%ISOTPMessageBuilder._feed_first_framec              	   C   s`   t |ƒdk rdS t |d¡d@ }|d|d … }|t |ƒkr@dS | j |||  |||¡f¡ dS )NrJ   Fr   é   rI   T)r5   r6   rP   r,   r4   r<   )r   rL   rQ   rN   r1   Úlengthr;   r   r   r   Ú_feed_single_frameè   s    
ÿz&ISOTPMessageBuilder._feed_single_framec           
      C   s    t |ƒdk rdS t |d¡}|d@ }|dd … }|||f}| j |d ¡}|d u rTdS | |¡ |jd u rŠ|d d }	|||	f}|| j|< n| j |||f¡ dS )NrJ   Fr   ra   rI   é   T)r5   r6   rP   r=   r   r0   r,   r4   )
r   rL   rQ   rN   Ú
first_byteZseq_nor;   r_   rY   Znext_seqr   r   r   Ú_feed_consecutive_frameù   s     



z+ISOTPMessageBuilder._feed_consecutive_framec                    s�   t |ƒdk rdS dd„ ˆ jˆ jfD ƒ}‡ fdd„|D ƒ}d ˆ _d ˆ _t|ƒrTt|ƒsXdS t||ƒD ](\}}|d u rtqb||_||_|ˆ j|< qbdS )NrZ   Fc                 S   s   g | ]}|d ur|‘qS r   r   )Ú.0Úxr   r   r   Ú
<listcomp>  r2   z@ISOTPMessageBuilder._feed_flow_control_frame.<locals>.<listcomp>c                    s   g | ]}ˆ j  |d ¡‘qS r   )r=   r   )rg   Úkr   r   r   ri     r2   T)r5   rA   rB   ÚanyÚzipr-   r.   r=   )r   rL   rQ   rN   Úkeysr=   r_   rY   r   r   r   Ú_feed_flow_control_frame  s    z,ISOTPMessageBuilder._feed_flow_control_framec                 C   s¬   t  |d¡}t|ƒdkr4|d@ tkr4|  ||||¡ t|ƒdkr\|d@ tkr\|  ||||¡ t|ƒdkr‚|d@ tkr‚|  |||¡ t|ƒdkr¨|d@ t	kr¨|  
|||¡ d S )Nr   rI   éð   rJ   )r6   rP   r5   r   rc   r   r`   r   rf   r   rn   )r   rL   rQ   rN   r1   re   r   r   r   rO   0  s    zISOTPMessageBuilder._try_feed)NN)r    r!   r"   r#   Úobjectr<   r   r   rK   Úpropertyr   rR   r   r   ÚstaticmethodrT   r`   rc   rf   rn   rO   r   r   r   r   r&   2   s(   ü

	
þr&   c                       s,   e Zd ZdZ‡ fdd„Z‡ fdd„Z‡  ZS )ÚISOTPSessionz`Defragment ISOTP packets 'on-the-flow'.

    Usage:
        >>> sniff(session=ISOTPSession)
    c                    sB   t t| ƒj|i |¤Ž t| dd ¡| dd ¡| dt¡d�| _d S )NrG   rH   r?   )rG   rH   r?   )Úsuperrs   r   r&   r   r   Úm)r   ÚargsÚkwargs©Ú	__class__r   r   r   D  s    


ýzISOTPSession.__init__c                    sV   |sd S | j  |¡ t| j ƒdkrR| j  ¡ }| jr@| j |¡ qtt| ƒ |¡ qd S r'   )ru   rK   r5   r   Z_supersessionÚon_packet_receivedrt   rs   )r   ZpktZrcvdrx   r   r   rz   L  s    
zISOTPSession.on_packet_received)r    r!   r"   r#   r   rz   Ú__classcell__r   r   rx   r   rs   =  s   rs   )r\   Zscapy.compatr   r   r   r   r   r   r   r	   Zscapy.utilsr
   Zscapy.packetr   Zscapy.sessionsr   Z scapy.contrib.isotp.isotp_packetr   r   r   r   r   Zscapy.libs.sixZlibsr6   rp   r   r&   rs   r   r   r   r   Ú<module>   s   (  