a
    kÄ#dßO  ã                   @   s\  d dl Z d dlZd dl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 d dlmZmZmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d d	lmZmZm 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$G dd„ de#e$ƒZ%eee!dd� eee!dd� eee!ddd� eee!dd� eee!dd� ee!edd� dS )é    N)Úlog_automotive)
ÚByteEnumFieldÚConditionalFieldÚ
XByteFieldÚXShortFieldÚ	XIntFieldÚXShortEnumFieldÚXByteEnumFieldÚIntFieldÚStrFixedLenFieldÚ	XStrField)ÚPacketÚbind_layersÚbind_bottom_up)ÚStreamSocket)ÚTCPÚUDP)ÚUDS)ÚMTU)ÚUnionÚTupleÚOptionalc                '   @   sä  e Zd ZdZdddddddd	d
ddddddddœZd Zeddƒeddƒeddeƒeddƒe	e
ddddddd d!œƒd"d#„ ƒe	ed$d%d&ƒd'd#„ ƒe	ed(dƒd)d#„ ƒe	ed*d%d+ƒd,d#„ ƒe	ed-d%d+ƒd.d#„ ƒe	ed/dd0d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d2d3œƒd4d#„ ƒe	ed5dd6d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d7d3œƒd8d#„ ƒe	ed9dƒd:d#„ ƒe	ed;dd<d=d>d<d?d>d@œƒdAd#„ ƒe	edBdƒdCd#„ ƒe	edDdƒdEd#„ ƒe	edFddGdHdIdJdKdLdMdNdOdOdOdOdOdOdOdOdPdQdRœƒdSd#„ ƒe	edTdƒdUd#„ ƒe	edVd%ƒdWd#„ ƒe	edXddYdZd[d\œƒd]d#„ ƒe	e
d^dd_d`daœƒdbd#„ ƒe	edcddƒded#„ ƒe	edfdƒdgd#„ ƒe	edhdƒdid#„ ƒe	edjdƒdkd#„ ƒe	edldddmiƒdnd#„ ƒe	e
dodd1d1dpdqdrddsdtdudvœ	ƒdwd#„ ƒe	edxd%ƒdyd#„ ƒgZdzd{„ Zd|d}„ Zd~d„ Zd€d�„ ZdS )‚ÚDoIPaü  
    Implementation of the DoIP (ISO 13400) protocol. DoIP packets can be sent
    via UDP and TCP. Depending on the payload type, the correct connection
    need to be chosen:

    +--------------+--------------------------------------------------------------+-----------------+
    | Payload Type | Payload Type Name                                            | Connection Kind |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0000       | Generic DoIP header negative acknowledge                     | UDP / TCP       |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0001       | Vehicle Identification request message                       | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0002       | Vehicle identification request message with EID              | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0003       | Vehicle identification request message with VIN              | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0004       | Vehicle announcement message/vehicle identification response | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0005       | Routing activation request                                   | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0006       | Routing activation response                                  | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0007       | Alive Check request                                          | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x0008       | Alive Check response                                         | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4001       | IP entity status request                                     | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4002       | DoIP entity status response                                  | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4003       | Diagnostic power mode information request                    | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x4004       | Diagnostic power mode information response                   | UDP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x8001       | Diagnostic message                                           | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x8002       | Diagnostic message positive acknowledgement                  | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+
    | 0x8003       | Diagnostic message negative acknowledgement                  | TCP             |
    +--------------+--------------------------------------------------------------+-----------------+

    Example with UDP:
        >>> socket = L3RawSocket(iface="eth0")
        >>> resp = socket.sr1(IP(dst="169.254.117.238")/UDP(dport=13400)/DoIP(payload_type=1))

    Example with TCP:
        >>> socket = DoIPSocket("169.254.117.238")
        >>> pkt = DoIP(payload_type=0x8001, source_address=0xe80, target_address=0x1000) / UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)

    Example with UDS:
        >>> socket = UDS_DoIPSocket("169.254.117.238")
        >>> pkt = UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)
    zGeneric DoIP header NACKzVehicle identification requestz'Vehicle identification request with EIDz'Vehicle identification request with VINzDVehicle announcement message/vehicle identification response messagezRouting activation requestzRouting activation responsezAlive check requestzAlive check responsezDoIP entity status requestzDoIP entity status responsez)Diagnostic power mode information requestz*Diagnostic power mode information responsezDiagnostic messagezDiagnostic message ACKzDiagnostic message NACK)r   é   é   é   é   é   é   é   é   é@  é@  é@  é@  é€  é€  é€  Zprotocol_versionr   Zinverse_versionéý   Úpayload_typer   Úpayload_lengthNZnackzIncorrect pattern formatzUnknown payload typezMessage too largezOut of memoryzInvalid payload length)r   r   r   r   r   c                 C   s
   | j dv S )N)r   ©r)   ©Úp© r.   úT/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/automotive/doip.pyÚ<lambda>n   ó    zDoIP.<lambda>Zvinr1   é   c                 C   s
   | j dv S )N)r   r   r+   r,   r.   r.   r/   r0   p   r1   Zlogical_addressc                 C   s
   | j dv S ©N)r   r+   r,   r.   r.   r/   r0   r   r1   Zeidr   c                 C   s
   | j dv S )N)r   r   r+   r,   r.   r.   r/   r0   t   r1   Úgidc                 C   s
   | j dv S r3   r+   r,   r.   r.   r/   r0   v   r1   Zfurther_actionzNo further action requiredzReserved by ISO 13400z8Routing activation required to initiate central security)r   r   r   r   r   r   r   r   r    é	   é
   é   é   é   é   é   é   c                 C   s
   | j dv S r3   r+   r,   r.   r.   r/   r0   ‚   r1   Zvin_gid_statuszVIN and/or GID are synchronizedz,Incomplete: VIN and GID are NOT synchronizedc                 C   s
   | j dv S r3   r+   r,   r.   r.   r/   r0   Ž   r1   Úsource_addressc                 C   s
   | j dv S )N)r   r    r%   r&   r'   r+   r,   r.   r.   r/   r0   �   r1   Úactivation_typeZDefaultzWWH-OBDzCentral securityZ
Diagnostic)r   r   éà   é   i  ià  c                 C   s
   | j dv S )N)r   r+   r,   r.   r.   r/   r0   ”   r1   Zlogical_address_testerc                 C   s
   | j dv S ©N)r   r+   r,   r.   r.   r/   r0   –   r1   Úlogical_address_doip_entityc                 C   s
   | j dv S rA   r+   r,   r.   r.   r/   r0   ˜   r1   Úrouting_activation_responsez8Routing activation denied due to unknown source address.zhRouting activation denied because all concurrently supported TCP_DATA sockets are registered and active.zˆRouting activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket.ziRouting activation denied because the SA is already registered and active on a different TCP_DATA socket.z8Routing activation denied due to missing authentication.z7Routing activation denied due to rejected confirmation.zERouting activation denied due to unsupported routing activation type.zfRouting activation denied because the specified activation type requires a secure TLS TCP_DATA socket.zReserved by ISO 13400.zRouting successfully activated.z1Routing will be activated; confirmation required.)r   r   r   r   r   r   r   r   r    r5   r6   r7   r8   r9   r:   r;   r<   r2   c                 C   s
   | j dv S rA   r+   r,   r.   r.   r/   r0   ©   r1   Zreserved_isoc                 C   s
   | j dv S ©N)r   r   r+   r,   r.   r.   r/   r0   «   r1   Úreserved_oemc                 C   s
   | j dv S rD   r+   r,   r.   r.   r/   r0   ­   r1   Zdiagnostic_power_modez	not readyÚreadyznot supported)r   r   r   c                 C   s
   | j dv S )N)r$   r+   r,   r.   r.   r/   r0   °   r1   Z	node_typezDoIP gatewayz	DoIP node)r   r   c                 C   s
   | j dv S ©N)r"   r+   r,   r.   r.   r/   r0   ³   r1   Zmax_open_socketsr   c                 C   s
   | j dv S rG   r+   r,   r.   r.   r/   r0   µ   r1   Zcur_open_socketsc                 C   s
   | j dv S rG   r+   r,   r.   r.   r/   r0   ·   r1   Zmax_data_sizec                 C   s
   | j dv S rG   r+   r,   r.   r.   r/   r0   ¹   r1   Útarget_addressc                 C   s
   | j dv S )N©r%   r&   r'   r+   r,   r.   r.   r/   r0   »   r1   Zack_codeZACKc                 C   s
   | j dv S )N)r&   r+   r,   r.   r.   r/   r0   ½   r1   Z	nack_codezInvalid source addresszUnknown target addresszDiagnostic message too largezTarget unreachablezUnknown networkzTransport protocol error)	r   r   r   r   r   r   r   r   r    c                 C   s
   | j dv S )N)r'   r+   r,   r.   r.   r/   r0   Ä   r1   Zprevious_msgc                 C   s
   | j dv S )N)r&   r'   r+   r,   r.   r.   r/   r0   Æ   r1   c                 C   sT   t |t| ƒƒrP| jdkrdS g d¢}| j|jf|v rP| jdkrL| j |j¡S dS dS )z)DEV: true if self is an answer from otherr   r   )	)r   r   )r   r   )r   r   )r   r   )r    r   )r"   r!   )r$   r#   )r%   r%   )r'   r%   r%   )Ú
isinstanceÚtyper)   ÚpayloadÚanswers)ÚselfÚotherÚmatchesr.   r.   r/   rM   É   s    

zDoIP.answersc                 C   s>   | j dv r.t| ƒd d… t d| j| jA ¡ S t| ƒd d… S )NrI   r   ÚH)r)   ÚbytesÚstructÚpackrH   r=   )rN   r.   r.   r/   ÚhashretÙ   s
    
ÿzDoIP.hashretc                 C   sF   | j du r>|dd… t dt|ƒt|ƒ d ¡ |dd…  }|| S )zP
        This will set the Field 'payload_length' to the correct value.
        Nr   z!Ir    )r*   rS   rT   Úlen)rN   ÚpktZpayr.   r.   r/   Ú
post_buildà   s
    
&
ÿzDoIP.post_buildc                 C   s(   | j dkr |d | jd … d fS dS d S )Nr%   r   )r1   N)r)   r*   )rN   Úsr.   r.   r/   Úextract_paddingê   s    
zDoIP.extract_padding)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Zpayload_typesÚnamer   r   r
   r   r   r   r   r	   r   r   Zfields_descrM   rU   rX   rZ   r.   r.   r.   r/   r      s0  8ð
ýüÿ
ÿÿÿöõöõ
ÿþý
ÿ
ÿñð
ÿ
ÿÿþÿþ
ÿ
ÿ
ÿ
ÿÿûú
ÿ d
r   c                   @   s2   e Zd ZdZddd	„Zejfd
d„Zddd„ZdS )Ú
DoIPSocketa3   Custom StreamSocket for DoIP communication. This sockets automatically
    sends a routing activation request as soon as a TCP connection is
    established.

    :param ip: IP address of destination
    :param port: destination port, usually 13400
    :param activate_routing: If true, routing activation request is
                             automatically sent
    :param source_address: DoIP source address
    :param target_address: DoIP target address, this is automatically
                           determined if routing activation request is sent
    :param activation_type: This allows to set a different activation type for
                            the routing activation request
    :param reserved_oem: Optional parameter to set value for reserved_oem field
                         of routing activation request

    Example:
        >>> socket = DoIPSocket("169.254.0.131")
        >>> pkt = DoIP(payload_type=0x8001, source_address=0xe80, target_address=0x1000) / UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)
    ú	127.0.0.1éX4  Té€  r   r1   c                 C   s2   || _ || _|| _|  ¡  |r.|  ||||¡ d S ©N)ÚipÚportr=   Ú_init_socketÚ_activate_routing©rN   re   rf   Zactivate_routingr=   rH   r>   rE   r.   r.   r/   Ú__init__  s    ÿzDoIPSocket.__init__c                 C   sV   t   |t j¡}| t jt jd¡ | t jt jd¡ | | j| j	f¡ t
 | |t¡ d S )Nr   )ÚsocketÚSOCK_STREAMÚ
setsockoptÚIPPROTO_TCPÚTCP_NODELAYÚ
SOL_SOCKETÚSO_REUSEADDRÚconnectre   rf   r   rj   r   )rN   Zsock_familyrY   r.   r.   r/   rg     s
    zDoIPSocket._init_socketc                 C   sd   | j td|||d�ddd�}|rP|jdkrP|jdkrP|p<|j| _t d| j¡ nt d	t	|ƒ¡ d S )
Nr   )r)   r>   r=   rE   Fr   )ÚverboseÚtimeoutr   r<   z:Routing activation successful! Target address set to: 0x%xz'Routing activation failed! Response: %s)
Zsr1r   r)   rC   rB   rH   r   ÚinfoÚerrorÚrepr)rN   r=   rH   r>   rE   Úrespr.   r.   r/   rh     s&    ÿýÿÿþÿzDoIPSocket._activate_routingN)ra   rb   Trc   r   r   r1   )r1   )	r[   r\   r]   r^   rj   rk   ÚAF_INETrg   rh   r.   r.   r.   r/   r`   ò   s      þ
 ür`   c                       s"   e Zd ZdZd
‡ fdd	„	Z‡  ZS )ÚDoIPSocket6aY   Custom StreamSocket for DoIP communication over IPv6.
    This sockets automatically sends a routing activation request as soon as
    a TCP connection is established.

    :param ip: IPv6 address of destination
    :param port: destination port, usually 13400
    :param activate_routing: If true, routing activation request is
                             automatically sent
    :param source_address: DoIP source address
    :param target_address: DoIP target address, this is automatically
                           determined if routing activation request is sent
    :param activation_type: This allows to set a different activation type for
                            the routing activation request
    :param reserved_oem: Optional parameter to set value for reserved_oem field
                         of routing activation request

    Example:
        >>> socket = DoIPSocket6("2001:16b8:3f0e:2f00:21a:37ff:febf:edb9")
        >>> pkt = DoIP(payload_type=0x8001, source_address=0xe80, target_address=0x1000) / UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)
    ú::1rb   Trc   r   r1   c                    sB   || _ || _|| _tt| ƒ tj¡ |r>tt| ƒ ||||¡ d S rd   )	re   rf   r=   Úsuperrz   rg   rk   ÚAF_INET6rh   ri   ©Ú	__class__r.   r/   rj   I  s    
ÿzDoIPSocket6.__init__)r{   rb   Trc   r   r   r1   )r[   r\   r]   r^   rj   Ú__classcell__r.   r.   r~   r/   rz   3  s
      þrz   c                       s0   e Zd ZdZ‡ fdd„Zef‡ fdd„	Z‡  ZS )ÚUDS_DoIPSocketa7  
    Application-Layer socket for DoIP endpoints. This socket takes care about
    the encapsulation of UDS packets into DoIP packets.

    Example:
        >>> socket = UDS_DoIPSocket("169.254.117.238")
        >>> pkt = UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)
    c                    sX   t |tƒr"td| j| jd�| }n|}zt ¡ |_W n tyF   Y n0 tt	| ƒ 
|¡S )Nr%   )r)   r=   rH   )rJ   r   r   r=   rH   ÚtimeZ	sent_timeÚAttributeErrorr|   r�   Úsend©rN   ÚxrW   r~   r.   r/   r„   a  s    
ÿÿzUDS_DoIPSocket.sendc                    s,   t t| ƒ |¡}|r$|jdkr$|jS |S d S )Nr%   )r|   r�   Úrecvr)   rL   r…   r~   r.   r/   r‡   p  s    zUDS_DoIPSocket.recv)r[   r\   r]   r^   r„   r   r‡   r€   r.   r.   r~   r/   r�   W  s   	r�   c                   @   s   e Zd ZdZdS )ÚUDS_DoIPSocket6aO  
    Application-Layer socket for DoIP endpoints. This socket takes care about
    the encapsulation of UDS packets into DoIP packets.

    Example:
        >>> socket = UDS_DoIPSocket6("2001:16b8:3f0e:2f00:21a:37ff:febf:edb9")
        >>> pkt = UDS() / UDS_RDBI(identifiers=[0x1000])
        >>> resp = socket.sr1(pkt, timeout=1)
    N)r[   r\   r]   r^   r.   r.   r.   r/   rˆ   y  s   	rˆ   rb   )Úsport)Údport)r‰   rŠ   r%   r+   )&rS   rk   r‚   Zscapy.contrib.automotiver   Zscapy.fieldsr   r   r   r   r   r   r	   r
   r   r   Zscapy.packetr   r   r   Zscapy.supersocketr   Zscapy.layers.inetr   r   Zscapy.contrib.automotive.udsr   Z
scapy.datar   Zscapy.compatr   r   r   r   r`   rz   r�   rˆ   r.   r.   r.   r/   Ú<module>   s,   0 XA$"