
    hX                        d dl Z d dlZd dlZd dlZd dl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mZmZmZmZmZmZ d dlmZmZ d dl m!Z!m"Z"m#Z# d d	l$m%Z%  G d
 de!          Z& e#ee&d            e#ee&d            e"ee&dd            e"ee&d            e"ee&d            e"e&ed            G d de%          Z' G d de'          Z( G d de(          Z)dS )    N)AnyUnionTupleOptionalDictType)log_automotive)UDS)MTU)ByteEnumFieldConditionalFieldIntFieldMayEndStrFixedLenFieldXByteEnumField
XByteField	XIntFieldXShortEnumFieldXShortField	XStrField)TCPUDP)Packetbind_layersbind_bottom_up)SSLStreamSocketc            )          e Zd ZdZi dddddddd	d
dddddd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/            e	 ed0d1d2          d3            e	 ed4d          d5            e	 ed6d1d          d7            e	 ed8d1d          d9            e	 e ed:di dd;dd<dd<dd<d
d<dd<dd<dd<dd<d=d<d>d<d?d<d@d<dAd<dBd<dCd<dDdE                    dF            e	 edGdi ddHdd<dd<dd<d
d<dd<dd<dd<dd<d=d<d>d<d?d<d@d<dAd<dBd<dCd<dDdI          dJ            e	 edKd          dL            e	 edMddNdOdPdNdQdPdR          dS            e	 edTd          dU            e	 edVd          dW            e	 edXdi ddYddZdd[dd\d
d]dd^dd_dd`ddad=dad>dad?dad@dadAdadBdadCdadDdbd2dci          dd            e	 eded          df            e	 edgd1          dh            e	 ediddjdkdldm          dn            e	 e
doddpdqdr          ds            e	 edtd          du            e	 edvd          dw            e	 edxd          dy            e	 edzd          d{            e	 ed|ddd}i          d~            e	 e
ddd<d<dddd,dddd	          d            e	 edd1          d           gZd Zd Zd Zd Ze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)
    r   zGeneric DoIP header NACK   zVehicle identification request   z'Vehicle identification request with EID   z'Vehicle identification request with VIN   zDVehicle announcement message/vehicle identification response message   zRouting activation request   zRouting activation response   zAlive check request   zAlive check response@  zDoIP entity status request@  zDoIP entity status response@  z)Diagnostic power mode information request@  z*Diagnostic power mode information response  zDiagnostic message  zDiagnostic message ACK  zDiagnostic message NACKprotocol_versioninverse_version   payload_typepayload_lengthNnackzIncorrect pattern formatzUnknown payload typezMessage too largezOut of memoryzInvalid payload length)r   r   r    r!   r"   c                     | j         dv S )N)r   r1   ps    a/mounts/lovelace/software/anaconda3/lib/python3.11/site-packages/scapy/contrib/automotive/doip.py<lambda>zDoIP.<lambda>   s    an-     vinr:      c                     | j         dv S )N)r!   r"   r5   r6   s    r8   r9   zDoIP.<lambda>       1>V#; r:   logical_addressc                     | j         dv S N)r"   r5   r6   s    r8   r9   zDoIP.<lambda>       1>S#8 r:   eidc                     | j         dv S )N)r    r"   r5   r6   s    r8   r9   zDoIP.<lambda>   r>   r:   gidc                     | j         dv S rA   r5   r6   s    r8   r9   zDoIP.<lambda>   rB   r:   further_actionzNo further action requiredzReserved by ISO 13400	   
                     z8Routing activation required to initiate central securityc                     | j         dv S rA   r5   r6   s    r8   r9   zDoIP.<lambda>   s    q~, r:   vin_gid_statuszVIN and/or GID are synchronizedz,Incomplete: VIN and GID are NOT synchronizedc                     | j         dv S rA   r5   r6   s    r8   r9   zDoIP.<lambda>       an+ r:   source_addressc                     | j         dv S )N)r#   r&   r+   r,   r-   r5   r6   s    r8   r9   zDoIP.<lambda>   s    1>5S#S r:   activation_typeDefaultzWWH-OBDzCentral security
Diagnostic)r   r         i  i  c                     | j         dv S )N)r#   r5   r6   s    r8   r9   zDoIP.<lambda>   rS   r:   logical_address_testerc                     | j         dv S N)r$   r5   r6   s    r8   r9   zDoIP.<lambda>   rB   r:   logical_address_doip_entityc                     | j         dv S r^   r5   r6   s    r8   r9   zDoIP.<lambda>   rB   r:   routing_activation_responsez8Routing activation denied due to unknown source address.zhRouting activation denied because all concurrently supported TCP_DATA sockets are registered and active.zRouting 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.c                     | j         dv S r^   r5   r6   s    r8   r9   zDoIP.<lambda>   rS   r:   reserved_isoc                     | j         dv S N)r#   r$   r5   r6   s    r8   r9   zDoIP.<lambda>   r>   r:   reserved_oemc                     | j         dv S re   r5   r6   s    r8   r9   zDoIP.<lambda>   r>   r:   diagnostic_power_modez	not readyreadyznot supported)r   r   r    c                     | j         dv S )N)r*   r5   r6   s    r8   r9   zDoIP.<lambda>       an0 r:   	node_typezDoIP gatewayz	DoIP node)r   r   c                     | j         dv S N)r(   r5   r6   s    r8   r9   zDoIP.<lambda>   rk   r:   max_open_socketsc                     | j         dv S rn   r5   r6   s    r8   r9   zDoIP.<lambda>       1>X#= r:   cur_open_socketsc                     | j         dv S rn   r5   r6   s    r8   r9   zDoIP.<lambda>   rq   r:   max_data_sizec                     | j         dv S rn   r5   r6   s    r8   r9   zDoIP.<lambda>   rq   r:   target_addressc                     | j         dv S )Nr+   r,   r-   r5   r6   s    r8   r9   zDoIP.<lambda>   s    1>5M#M r:   ack_codeACKc                     | j         dv S )N)r,   r5   r6   s    r8   r9   zDoIP.<lambda>   rq   r:   	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                     | j         dv S )N)r-   r5   r6   s    r8   r9   zDoIP.<lambda>   rk   r:   previous_msgc                     | j         dv S )N)r,   r-   r5   r6   s    r8   r9   zDoIP.<lambda>   s    1>5E#E r:   c                     t          |t          |                     rM| j        dk    rdS g d}| j        |j        f|v r,| j        dk    r| 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typer1   payloadanswers)selfothermatchess      r8   r   zDoIP.answers   s     eT$ZZ(( 
	 A%%q; ; ;G !5#56'AA$..<//>>>qqr:   c                     | j         dv r:t          |           d d         t          j        d| j        | j        z            z   S t          |           d d         S )Nrx   r    H)r1   bytesstructpackrv   rT   )r   s    r8   hashretzDoIP.hashret   sb     888;;rr?V[T(4+>>&@ &@ @ @T{{2A2r:   c                     | j         K|dd         t          j        dt          |          t          |          z   dz
            z   |dd         z   }||z   S )zP
        This will set the Field 'payload_length' to the correct value.
        Nr"   !Ir&   )r2   r   r   len)r   pktpays      r8   
post_buildzDoIP.post_build   sb    
 &bqb'FKc#hhS)A-/ / /14QRR9CSyr:   c                 h    | j         dk    r$|d | j        dz
           || j        dz
  d          fS d|fS )Nr+   r"   r:   )r1   r2   )r   ss     r8   extract_paddingzDoIP.extract_padding  sJ    &&-d)A--.$2E2I2J2J0KKK6Mr:   c                     t          j        d|dd                   d         dz   }t          |          |k    rt          |          S d S )Nr   r"   r&   r   )r   unpackr   r   )clsdatametadatasessionlengths        r8   tcp_reassemblezDoIP.tcp_reassemble  sI     tT!A#Y//2Q6t99::tr:   )__name__
__module____qualname____doc__payload_typesnamer   r   r   r   r   r   r   r   r   r   r   fields_descr   r   r   r   classmethodr    r:   r8   r   r   0   s       6 6n+*+0+ 	9+ 	9	+
 	V+ 	,+ 	-+ 	%+ 	&+ 	,+ 	-+ 	;+ 	<+ 	$+ 	(+  	)!+M" D
%t,,
$d++=99!4((vq).D"'3
 3
   .-		/ 	/
 	))%b99;;	= 	=%6::88	: 	:))%a88;;	= 	=))%a8888	: 	:/? E
.E
)E
+/1HE
 )E
 ,01HE
 )	E
 ,01H	E

 )E

 ,01HE
 )E
 ,01HE
 )E
 ,01HE
 )E
 ,01HE
 )E
 LE
 ! !   -,	. 	. 	(8! >
3>
)>
+/1H>
 )>
 ,01H>
 )	>
 ,01H	>

 )>

 ,01H>
 )>
 ,01H>
 )>
 ,01H>
 )>
 ,01H>
 )>
 @>
   ,+	- 	- 	%5q99SS	U 	U(91Y.@L:L?
 ?
   ,+	- 	- 	%=qAA88	: 	:%BAFF88	: 	:(Eq K
LK
|K
   ]K
 }	K

 LK
 KK
 YK
 zK
 *K
 *K
 -12JK
 *K
 -12JK
 *K
 -12JK
 *K
 3K
 EK
 K
    ,+!	- 	-" 	>155;;	= 	=>377;;	= 	=(?w?E
 E
  00	2 	2 	{A+8
 8
  00	2 	2 	$6::==	? 	?$6::==	? 	?/155==	? 	?%5q99MM	O 	O
A5zBB==	? 	?{A)1H*2J0&.?,8
 8
   10	2 	2 	>377EE	G 	GEdKL            [  r:   r   X4  )sport)dport)r   r   r+   r5   c                   .     e Zd ZdZd fd	ZefdZ xZS )DoIPSSLStreamSocketz3Custom SSLStreamSocket for DoIP communication.
    Nc                 v    t          t          |                               ||pt                     d| _        d S )Nr:   )superr   __init__r   buffer)r   sockbasecls	__class__s      r8   r   zDoIPSSLStreamSocket.__init__  s3    !4((11$4HHHr:   c                 8   t          | j                  dk     r(| xj        | j                            d          z  c_        t          | j                  dk     rd S | j        d d         }t	          j        d|dd                   d         }|dz  }| xj        | j                            |t          | j                  z
            z  c_        t          | j                  |k     rd S | j        d |         }| j        |d          | _         | j        |fi |}|S )Nr&   z>Ir"   r   )r   r   insrecvr   r   r   )r   xkwargslen_datalen_intpktbufr   s          r8   r   zDoIPSSLStreamSocket.recv$  s   t{aKK48==+++KKt{a4;rr?-hqsm44Q71tx}}Ws4;/?/?%?@@@t{g%%4XgX&k'((+dl6,,V,,
r:   N)r   r   r   r   r   r   r   __classcell__r   s   @r8   r   r     s`              
         r:   r   c                   :    e Zd ZdZ	 	 	 	 	 	 	 	 	 	 ddZd Zd Zd
S )
DoIPSocketab  Socket for DoIP communication. This sockets automatically
    sends a routing activation request as soon as a TCP or TLS connection is
    established.

    :param ip: IP address of destination
    :param port: destination port, usually 13400
    :param tls_port: destination port for TLS connection, usually 3496
    :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
    :param force_tls: Skip establishing of a TCP connection and directly try to
                      connect via SSL/TLS
    :param context: Optional ssl.SSLContext object for initialization of ssl socket
                    connections.

    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.1r     T  r   r:   FNc                    || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        	 | 
                                 d S # t          $ r |                                   w xY wr   )ipporttls_portactivate_routingrT   rv   rV   rf   	force_tlscontext_init_socket	Exceptionclose)r   r   r   r   r   rT   rv   rV   rf   r   r   s              r8   r   zDoIPSocket.__init__U  s     	  0,,.("	 	 	 	JJLLL	s   A  A>c                    d}t          j        | j        | j        t           j                  }|d         d         }t          j         |t           j                  }|                    d           |                    t           j        t           j        d           |                    t           j	        t           j
        d           | j        s\|                    |d         d                    d}t                              | |           | j        sd S |                                 }nd}|d	k    rd S |dk    rn| j        t%          d
          |r|                                 t          j         |t           j                  }|                    d           |                    t           j        t           j        d           |                    t           j	        t           j
        d           | j                            |          }t          j        | j        | j        t           j                  }|                    |d         d                    t                              | |           | j        sd S |                                 }|d	k    rd S t-          d|z            |dk    rt-          d          t-          d|z            )NF)protor   r#   r   Tr%   rO   z$SSLContext 'context' can not be NonezHDoIPSocket activate_routing failed with routing_activation_response 0x%xz#DoIPSocket._activate_routing failedzIDoIPSocket activate_routing failed with routing_activation_response 0x%x!)socketgetaddrinfor   r   IPPROTO_TCPSOCK_STREAM
settimeout
setsockoptTCP_NODELAY
SOL_SOCKETSO_REUSEADDRr   connectr   r   r   _activate_routingr   
ValueErrorr   wrap_socketr   r   )r   	connectedaddrinfosock_familyr   activation_returnsss          r8   r   zDoIPSocket._init_socketq  s   	%dgty@RSSSqk!nM+v'9::	Q	V');Q???	V&(;Q???~ 	%IIhqk"o&&&I((q111(  $ 6 6 8 8 !%$$F$&& |# !GHHH H			M+v/ABBQV/1CQGGGV.0CQGGG))!,,B)f.@B B BHJJx{2'''((r222(  $ 6 6 8 8 D((79JKL L L "$$ABBB46GHI I Ir:   c                 n   |                      t          d| j        | j        | j                  dd          }|rD|j        dk    r9|j        dk    r.| j        p|j        | _        t          j
        d| j                   n"t          j        d	t          |                     |r|j        dk    r|j        S d
S )Nr#   )r1   rV   rT   rf   Fr   )verbosetimeoutr$   rO   z:Routing activation successful! Target address set to: 0x%xz'Routing activation failed! Response: %sr   )sr1r   rV   rT   rf   r1   ra   rv   r_   r	   infoerrorrepr)r   resps     r8   r   zDoIPSocket._activate_routing  s    xxc43G $ 3$BSU U U1  & &  		GD%,,0D88#Gt'G L#% % % %  94::G G G  	D%,,332r:   )
r   r   r   Tr   r   r   r:   FN)r   r   r   r   r   r   r   r   r:   r8   r   r   9  st         8  "& % !!"!    8>I >I >I@    r:   r   c                   0     e Zd ZdZ fdZef fd	Z x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                    t          |t                    r t          d| j        | j                  |z  }n|}	 t          j                    |_        n# t          $ r Y nw xY wt                      	                    |          S )Nr+   )r1   rT   rv   )
r   r
   r   rT   rv   time	sent_timeAttributeErrorr   send)r   r   r   r   s      r8   r   zUDS_DoIPSocket.send  s    a 	F&*&9&*&9   CC
 C	)++AKK 	 	 	D	 ww||C   s   A 
A A c                 d     t                      j        |fi |}|r|j        dk    r|j        S |S )Nr+   )r   r   r1   r   )r   r   r   r   r   s       r8   r   zUDS_DoIPSocket.recv  sB    eggl1'''' 	3#v--;Jr:   )r   r   r   r   r   r   r   r   r   s   @r8   r   r     s\         ! ! ! ! !"        	DDDr:   r   )*r   sslr   r   typingr   r   r   r   r   r   scapy.contrib.automotiver	   scapy.contrib.automotive.udsr
   
scapy.datar   scapy.fieldsr   r   r   r   r   r   r   r   r   r   r   scapy.layers.inetr   r   scapy.packetr   r   r   scapy.supersocketr   r   r   r   r   r   r:   r8   <module>r      s    



                  4 3 3 3 3 3 , , , , , ,                                ' & & & & & & & < < < < < < < < < < - - - - - -^ ^ ^ ^ ^6 ^ ^ ^B sD & & & & sD & & & & CU% 0 0 0 0 CU # # # # CU # # # # D#F + + + +    /   <K K K K K$ K K K\$	 $	 $	 $	 $	Z $	 $	 $	 $	 $	r:   