a
    kÄ#do*  ã                   @   sR  d dl Z d dlZd dlmZmZmZmZmZ d dlm	Z	 d dl
mZmZmZmZmZmZ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 e d¡Zd	Zd
ZdZ dZ!dZ"dddddœZ#d Z$d
Z%dZ&dZ'G dd„ de	ƒZ(G dd„ deƒZ)G dd„ de)ƒZ*dddddœZ+G dd„ de	ƒZ,G dd„ de	ƒZ-G dd „ d e	ƒZ.G d!d"„ d"e	ƒZ/dS )#é    N)ÚOptionalÚListÚTupleÚAnyÚType)ÚPacket)ÚBitFieldÚ
FlagsFieldÚStrLenFieldÚThreeBytesFieldÚ	XBitFieldÚConditionalFieldÚBitEnumFieldÚ	ByteFieldÚ
XByteFieldÚBitFieldLenFieldÚStrField)ÚchbÚorb)ÚCAN)ÚScapy_Exceptionzscapy.contrib.isotpiÿÿÿé   é   l   ÿÿ iÿ  ÚsingleÚfirstZconsecutiveZflow_control)r   é   é   é   é    é0   c                   @   sT   e Zd ZdZd ZeddƒgZejg d¢ Zdd„ Z	dd„ Z
d	d
„ Zeddd„ƒZdS )ÚISOTPa  Packet class for ISOTP messages. This class contains additional
    slots for source address (tx_id), destination address (rx_id),
    extended source address (ext_address) and
    extended destination address (rx_ext_address) information. This information
    gets filled from ISOTPSockets or the ISOTPMessageBuilder, if it
    is available. Address information is not used for Packet comparison.

    :param args: Arguments for Packet init, for example bytes string
    :param kwargs: Keyword arguments for Packet init.
    Údataó    )Útx_idÚrx_idÚext_addressÚrx_ext_addressc                 O   s\   |  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _tj| g|¢R i |¤Ž |  ¡  d S )Nr#   r$   r%   r&   )Úpopr#   r$   r%   r&   r   Ú__init__Úvalidate_fields)ÚselfÚargsÚkwargs© r-   úW/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/isotp/isotp_packet.pyr(   8   s    zISOTP.__init__c                 C   s¬   | j dur*d| j   kr tks*n tdƒ‚| jdurTd| j  krJtksTn tdƒ‚| jdur~d| j  krtdks~n tdƒ‚| jdur¨d| j  krždks¨n tdƒ‚dS )znHelper function to validate information in tx_id, rx_id,
        ext_address and rx_ext_address slots
        Nr   z#tx_id is not a valid CAN identifierz#rx_id is not a valid CAN identifieréÿ   zext_address is not a bytezrx_ext_address is not a byte)r#   ÚCAN_MAX_IDENTIFIERr   r$   r%   r&   )r*   r-   r-   r.   r)   A   s    



zISOTP.validate_fieldsc                 O   s  d}| j durd}t| jƒtkr(tdƒ‚t| jƒ|kr t dt| jƒ¡| j }| j rft d| j ¡| }| jdu sz| jdkrŠt| j|d�}nt| jd|d	�}|gS t| jƒt	krÆt d
t| jƒd ¡}nt ddt| jƒ¡}| j ròt d| j ¡| }dt|ƒ }| jd|… }| jdu �s$| jdk�r8t| j|| d�}nt| jd|| d	�}d}	|g}
|t| jƒk �r| j||| … }t d|	d t
 ¡}|	d7 }	|t|ƒ7 }| j �rºt d| j ¡| }| jdu �sÒ| jdk�ræt| j|| d�}nt| jd|| d	�}|
 |¡ �qV|
S )z~Helper function to fragment an ISOTP message into multiple
        CAN frames.

        :return: A list of CAN frames
        é   Né   zToo much data in ISOTP messageÚBiÿ  )Ú
identifierr!   Úextended)r4   Úflagsr!   z>Hi   z>HIr   r   r   Úbr   )r&   Úlenr!   ÚISOTP_MAX_DLEN_2015r   ÚstructÚpackr$   r   ÚISOTP_MAX_DLENÚN_PCI_CFÚappend)r*   r+   ZkargsZdata_bytes_in_frameZ
frame_dataÚpktZframe_headerÚidxÚframeÚnZpktsr-   r-   r.   ÚfragmentS   sV    
ÿÿÿzISOTP.fragmentNc                    sÆ   ddl m} t| ƒdkr tdƒ‚| d j‰ t‡ fdd„| D ƒƒrJt d¡ ||ƒ}| | ¡ g }|D ]:}|du rz|j	dus”|d	u rŒ|j	du s”|du rd| 
|¡ qd|s¨dS t|ƒd
kr¾t d¡ |d S )a£  Helper function to defragment a list of CAN frames to one ISOTP
        message

        :param can_frames: A list of CAN frames
        :param use_extended_addressing: Specify if extended ISO-TP addressing
                                        is used in the packets for
                                        defragmentation.
        :return: An ISOTP message containing the data of the CAN frames or None
        r   )ÚISOTPMessageBuilderz%ISOTP.defragment called with 0 framesc                 3   s   | ]}|j ˆ kV  qd S ©N)r4   )Ú.0rA   ©Údstr-   r.   Ú	<genexpr>£   r"   z#ISOTP.defragment.<locals>.<genexpr>z+Not all CAN frames have the same identifierTNFr   zkMore than one ISOTP frame could be defragmented from the provided CAN frames, only returning the first one.)Zscapy.contrib.isotp.isotp_utilsrD   r8   r   r4   ÚanyÚ	log_isotpÚwarningÚfeedr&   r>   )Z
can_framesZuse_extended_addressingrD   ÚparserÚresultsÚpr-   rG   r.   Ú
defragment‘   s6    


ÿþýüÿzISOTP.defragment)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Únamer   Úfields_descr   Ú	__slots__r(   r)   rC   ÚstaticmethodrQ   r-   r-   r-   r.   r    '   s   
ÿ	>r    c                   @   sV   e Zd Zd Zedddg d¢ƒedddƒeddƒed	dƒgZd
d„ Z	dd„ Z
dd„ ZdS )ÚISOTPHeaderr6   r   r   ©ÚerrorZremote_transmission_requestr5   r4   é   ÚlengthNÚreservedc                 C   s   |d fS rE   r-   )r*   rP   r-   r-   r.   Úextract_paddingÈ   s    zISOTPHeader.extract_paddingc                 C   s6   | j du r.|dd… tt|ƒƒ |dd…  }|| S )zL
        This will set the ByteField 'length' to the correct value.
        Né   é   ©r^   r   r8   )r*   r?   Úpayr-   r-   r.   Ú
post_buildÌ   s    
$zISOTPHeader.post_buildc                 C   s@   t |d ƒd@ d? }|dkr tS |dkr,tS |dkr8tS tS dS )zÏISO-TP encodes the frame type in the first nibble of a frame. This
        is used to determine the payload_class

        :param payload: payload bytes string
        :return: Type of payload class
        r   éð   ra   r   r   N)r   ÚISOTP_SFÚISOTP_FFÚISOTP_CFÚISOTP_FC)r*   ÚpayloadÚtr-   r-   r.   Úguess_payload_classÕ   s    zISOTPHeader.guess_payload_class)rR   rS   rT   rV   r	   r   r   r   rW   r`   re   rm   r-   r-   r-   r.   rZ   ½   s   
ú		rZ   c                   @   sN   e Zd ZdZedddg d¢ƒedddƒedd	ƒed
dƒeddƒgZ	dd„ Z
d	S )ÚISOTPHeaderEAZISOTPHeaderExtendedAddressr6   r   r   r[   r4   r]   r^   Nr_   Zextended_addressc                 C   s:   | j du r2|dd… tt|ƒd ƒ |dd…  }|| S )zÉ
        This will set the ByteField 'length' to the correct value.
        'chb(len(pay) + 1)' is required, because the field 'extended_address'
        is counted as payload on the CAN layer
        Nra   r   rb   rc   )r*   rP   rd   r-   r-   r.   re   ô   s    
(zISOTPHeaderEA.post_build)rR   rS   rT   rV   r	   r   r   r   r   rW   re   r-   r-   r-   r.   rn   è   s   
ù
rn   c                   @   s>   e Zd ZdZedddeƒeddddd�edd	d
d„ d�gZdS )rg   ZISOTPSingleFrameÚtyper   ra   Úmessage_sizeNr!   )Z	length_ofr"   c                 C   s   | j S rE   ©rp   ©r?   r-   r-   r.   Ú<lambda>  r"   zISOTP_SF.<lambda>)Zlength_from)	rR   rS   rT   rV   r   Ú
ISOTP_TYPEr   r
   rW   r-   r-   r-   r.   rg     s
   ýrg   c                   @   sJ   e Zd ZdZedddeƒedddƒeeddd	ƒd
d„ ƒedddd�gZ	dS )rh   ZISOTPFirstFramero   r   ra   rp   r   é   Zextended_message_sizer   c                 C   s
   | j dkS )Nr   rq   rr   r-   r-   r.   rs     r"   zISOTP_FF.<lambda>r!   r"   r3   ©ÚfmtN)
rR   rS   rT   rV   r   rt   r   r   r   rW   r-   r-   r-   r.   rh     s   
ÿûrh   c                   @   s6   e Zd ZdZedddeƒedddƒeddd	d
�gZdS )ri   ZISOTPConsecutiveFramero   r   ra   Úindexr   r!   r"   r3   rv   N)	rR   rS   rT   rV   r   rt   r   r   rW   r-   r-   r-   r.   ri     s
   
ýri   c                	   @   sD   e Zd ZdZedddeƒedddddd	d
œƒeddƒeddƒgZdS )rj   ZISOTPFlowControlFramero   r   ra   Zfc_flagr   ÚcontinueÚwaitÚabort)r   r   r   Ú
block_sizeZseparation_timeN)rR   rS   rT   rV   r   rt   r   rW   r-   r-   r-   r.   rj   #  s   
þúrj   )0r:   ÚloggingZscapy.compatr   r   r   r   r   Zscapy.packetr   Zscapy.fieldsr   r	   r
   r   r   r   r   r   r   r   r   r   r   Zscapy.layers.canr   Zscapy.errorr   Ú	getLoggerrK   r0   ZCAN_MTUZCAN_MAX_DLENr9   r<   ZISOTP_TYPESZN_PCI_SFZN_PCI_FFr=   ZN_PCI_FCr    rZ   rn   rt   rg   rh   ri   rj   r-   r-   r-   r.   Ú<module>	   sF   4
ý +ý		