a
    kÄ#d‡.  ã                   @   sª  d dl Z d dlmZ d dl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mZmZmZmZmZmZmZmZmZ d dlm  mZ d	d
dddddddddddddœZdd„ Zdd„ Z G dd„ deƒZ!e	ee!dd� e	ee!dd � i ej"d!< G d"d#„ d#eƒZ#G d$d%„ d%eƒZ$G d&d'„ d'eƒZ%g d(¢Z&g d)¢Z'G d*d+„ d+eƒZ(G d,d-„ d-e(ƒZ)G d.d/„ d/e(ƒZ*G d0d1„ d1eƒZ+G d2d3„ d3e+ƒZ,G d4d5„ d5e+ƒZ-dS )6é    N)Úraw©ÚScapy_Exception)Úconf)ÚPacketÚbind_layers)ÚEther)ÚUDP)ÚXShortEnumFieldÚBitEnumFieldÚ	XBitFieldÚBitFieldÚStrFieldÚPacketListFieldÚStrFixedLenFieldÚ
ShortFieldÚ
FlagsFieldÚ	ByteFieldÚ	XIntFieldÚX3BytesFieldzPTCP-RTSyncPDU-followupzPTCP-RTSyncPDUz
Alarm Highz	Alarm LowzDCP-Hello-ReqzDCP-Get-SetzDCP-Identify-ReqPDUzDCP-Identify-ResPDUzPTCP-AnnouncePDUzPTCP-FollowUpPDUzPTCP-DelayReqPDUzPTCP-DelayResPDU-followupzPTCP-DelayFuResPDUzPTCP-DelayResPDU)é    é€   éü  éþ  iüþ  éýþ  éþþ  éÿþ  i ÿ  i ÿ  i@ÿ  iAÿ  iBÿ  iCÿ  c                 C   s¢   z
t |  W S  ty   Y n0 d|   kr2dk r>n nd|  S d|   krRdk r^n nd|  S d|   krrdk r~n nd|  S d	|   kr’d
k ržn nd|  S | S )zx Get representation name of a pnio frame ID

    :param x: a key of the PNIO_FRAME_IDS dictionary
    :returns: str
    é   é   zRT_CLASS_3 (%4x)é €  é À  zRT_CLASS_1 (%4x)é ü  zRT_CLASS_UDP (%4x)é€ÿ  i�ÿ  zFragmentationFrameID (%4x))ÚPNIO_FRAME_IDSÚKeyError©Úx© r'   úI/var/www/html/gsl.tools/lib/python3.9/site-packages/scapy/contrib/pnio.pyÚi2s_frameid)   s    
r)   c                    s^   zdddddœˆ  W S  t y&   Y n0 zt‡ fdd„t t¡D ƒƒW S  tyX   Y n0 ˆ S )z³ Get pnio frame ID from a representation name

    Performs a reverse look-up in PNIO_FRAME_IDS dictionary

    :param x: a value of PNIO_FRAME_IDS dict
    :returns: integer
    r   r   r    r"   )Z
RT_CLASS_3Z
RT_CLASS_1ZRT_CLASS_UDPZFragmentationFrameIDc                 3   s   | ]\}}|ˆ kr|V  qd S ©Nr'   )Ú.0ÚkeyÚvaluer%   r'   r(   Ú	<genexpr>P   s   
ÿzs2i_frameid.<locals>.<genexpr>)r$   ÚnextÚsixÚ	iteritemsr#   ÚStopIterationr%   r'   r%   r(   Ús2i_frameid>   s    üûr3   c                       s2   e Zd ZdZeddeefƒgZ‡ fdd„Z‡  Z	S )Ú
ProfinetIOz Basic PROFINET IO dispatcher ÚframeIDr   c                    s”   | j dv rddlm} |S | j dkr4ddlm} |S | j dkrNddlm} |S d| j   krdd	k s€n d
| j   kr|dk r„n ntS tt| ƒ 	|¡S )N)r   r   r   r   )ÚProfinetDCPr   )Ú	Alarm_Lowr   )Ú
Alarm_Highr   r   r   r!   )
r5   Zscapy.contrib.pnio_dcpr6   Zscapy.contrib.pnio_rpcr7   r8   ÚPNIORealTimeCyclicPDUÚsuperr4   Úguess_payload_class)ÚselfÚpayloadr6   r7   r8   ©Ú	__class__r'   r(   r;   a   s&    


ÿÿþþ
zProfinetIO.guess_payload_class)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r
   r)   r3   Úfields_descr;   Ú__classcell__r'   r'   r>   r(   r4   [   s   ÿr4   i’ˆ  )Útype)ÚdportÚPNIO_RTCc                   @   sl   e Zd ZdZdZedddddgƒeddd	g d
¢ƒedddƒedddƒgZe	dd„ ƒZ
e	dd„ ƒZdd„ ZdS )ÚPNIORealTime_IOxSz6 IOCS and IOPS packets for PROFINET Real-Time payload zPNIO RTC IOxSZ	dataStateé   ÚbadZgoodÚinstancer   é   )ZsubslotÚslotZdeviceÚ
controllerÚreservedé   Ú	extensionc                 C   s$   t |td ƒƒs|jdkr| nd }|S ©Nr   )Ú
isinstancerF   rR   )ÚclsZ_pktÚ_lstÚpÚ_remainÚretr'   r'   r(   Úis_extension_set�   s     z"PNIORealTime_IOxS.is_extension_setc                 C   s   t dd„ | jD ƒƒS )Nc                 s   s   | ]}t |ƒ d d¡V  qd S rS   )rF   Zi2len)r+   Zfldr'   r'   r(   r.   —   ó    z,PNIORealTime_IOxS.get_len.<locals>.<genexpr>)ÚsumrD   )rU   r'   r'   r(   Úget_len•   s    zPNIORealTime_IOxS.get_lenc                 C   s   t jS r*   ©r   Zpadding_layer©r<   rW   r'   r'   r(   r;   ™   s    z%PNIORealTime_IOxS.guess_payload_classN)r@   rA   rB   rC   Únamer   r   r   rD   ÚclassmethodrZ   r]   r;   r'   r'   r'   r(   rI   �   s   ÿ

÷

rI   c                   @   s(   e Zd ZdZedddd�gZdd„ ZdS )	Ú PNIORealTimeCyclicDefaultRawDataz-PROFINET IO Real Time Cyclic Default Raw DataÚdataÚ rQ   )Úremainc                 C   s   t jS r*   r^   )r<   r=   r'   r'   r(   r;   ¥   s    z4PNIORealTimeCyclicDefaultRawData.guess_payload_classN)r@   rA   rB   r`   r   rD   r;   r'   r'   r'   r(   rb   �   s   ýrb   c                	   @   s�   e Zd ZdZddgZdZedg dd„ d�ed	d
dd„ d�eddƒe	dddg d¢ƒe
ddƒgZdd„ Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZdS )r9   z PROFINET cyclic real-time Ú_lenÚ_layoutzPROFINET Real-Timerc   c                 C   s   |   |||¡S r*   ©Únext_cls_cb)ÚpktÚlstrW   re   r'   r'   r(   Ú<lambda>²   s   ÿzPNIORealTimeCyclicPDU.<lambda>rh   Úpaddingrd   c                 C   s   |   ¡ S r*   )Úget_padding_length©rW   r'   r'   r(   rl   ·   r[   ©Zlength_fromZcycleCounterr   Z
dataStatusé5   é   )ÚprimaryZ
redundancyZ	validDataZ
reserved_1ÚrunZ
no_problemZ
reserved_2ÚignoreZtransferStatusc                 C   s   t dt|ƒƒ| _|S )Ni   )ÚminÚlenrf   )r<   Úsr'   r'   r(   Úpre_dissectÇ   s    z!PNIORealTimeCyclicPDU.pre_dissectc                 C   s¦   t | dƒr6| jtdd„ |  d¡D ƒƒ d d d }nt|  d¡ƒ}d|  krXd	ks^n J ‚| }t|tƒs~t |d
ƒr~|j}qbt|tƒr¢d|  krœdks¢n J ‚|S )Nrf   c                 s   s   | ]}t t|ƒƒV  qd S r*   )rw   r   )r+   rj   r'   r'   r(   r.   Ð   r[   z;PNIORealTimeCyclicPDU.get_padding_length.<locals>.<genexpr>rc   rM   rJ   rm   r   é(   Ú
underlayeré   )Úhasattrrf   r\   Zgetfieldvalrw   rT   r	   r{   )r<   Zpad_lenÚqr'   r'   r(   rn   Ì   s&    
ÿþýüÿ
z(PNIORealTimeCyclicPDU.get_padding_lengthc                 C   sô   t | dƒr@t| jtƒr@z| j d¡W S  ty>   d | _Y d S 0 d }| }t|tƒsdt |dƒrd|j}qHt|tƒrr|}d }| }t|tƒs–t |dƒr–|j}qzt|tƒr¤|}t	g| _|d u r¼|d u sèt
| ƒ |j|j|j¡}t|t
d ƒƒsè|| _| j d¡S )Nrg   r   r{   )r}   rT   rg   ÚlistÚpopÚ
IndexErrorr   r{   r4   rb   rF   Úget_layout_from_configÚsrcÚdstr5   )r<   rV   Ú_prX   Zether_layerr~   Z
pnio_layerZlayoutr'   r'   r(   ri   á   s8    

ýz!PNIORealTimeCyclicPDU.next_cls_cbc                 C   s6   zt  tjd | ||f ¡W S  ty0   Y d S 0 d S )NrH   )ÚcopyÚdeepcopyr   Úcontribsr$   )Z	ether_srcZ	ether_dstZframe_idr'   r'   r(   r‚     s    ÿz,PNIORealTimeCyclicPDU.get_layout_from_configc              	      s>   t d ˆ ¡tjfd ˆ ¡tddˆ d�g‡ fdd„dd„ dœƒS )	NzFixedLenRawPacketLen{}rc   rd   ©Úlengthc                    s   ˆ S r*   r'   ©Ú_r‰   r'   r(   rl     r[   z@PNIORealTimeCyclicPDU.build_fixed_len_raw_type.<locals>.<lambda>c                 S   s   t jS r*   r^   r_   r'   r'   r(   rl     r[   )r`   rD   Úget_data_lengthr;   )rF   Úformatr   Z	raw_layerr   r‰   r'   r‰   r(   Úbuild_fixed_len_raw_type  s    
üýz.PNIORealTimeCyclicPDU.build_fixed_len_raw_typeN)r@   rA   rB   rC   Ú	__slots__r`   r   r   r   r   r   rD   ry   rn   ri   Ústaticmethodr‚   r�   r'   r'   r'   r(   r9   ©   s*   þÿ
ê"
r9   )ZiPar_ENZOA_ReqZ	R_cons_nrZUse_TO2Zactivate_FVZToggle_hZChF_AckZ	Loopcheck)ZiPar_OKzDevice_Fault/ChF_Ack_ReqZCE_CRCZ
WD_timeoutZFV_activatedZToggle_dZ	cons_nr_RrP   c                   @   s<   e Zd Zdgej Zdd„ Zdd„ Zdd„ Zedd	„ ƒZ	d
S )ÚPROFIsafeCRCSeedrf   c                 C   s   t jS r*   r^   r_   r'   r'   r(   r;   )  s    z$PROFIsafeCRCSeed.guess_payload_classc                 C   s   t dƒ‚dS ©z> Must be overridden in a subclass to return the correct value z5This method must be overridden in a specific subclassNr   ©r<   r'   r'   r(   r�   ,  s    ÿz PROFIsafeCRCSeed.get_data_lengthc                 C   s   dS )Né   r'   r”   r'   r'   r(   Úget_mandatory_fields_len2  s    z)PROFIsafeCRCSeed.get_mandatory_fields_lenc                   C   s   dS )Né   r'   r'   r'   r'   r(   Úget_max_data_length6  s    z$PROFIsafeCRCSeed.get_max_data_lengthN)
r@   rA   rB   r   r�   r;   r�   r–   r‘   r˜   r'   r'   r'   r(   r’   &  s   r’   c                   @   s8   e Zd ZdZedddd„ d�eddd	eƒed
dƒgZdS )ÚPROFIsafeControlCRCSeedz+PROFISafe Control Message with F_CRC_Seed=1rc   rd   c                 C   s   |   ¡ S r*   ©r�   ro   r'   r'   r(   rl   @  r[   z PROFIsafeControlCRCSeed.<lambda>rp   Úcontrolr   rr   ÚcrcN)	r@   rA   rB   r`   r   r   Úprofisafe_control_flagsr   rD   r'   r'   r'   r(   r™   <  s   ÿür™   c                   @   s8   e Zd ZdZedddd„ d�eddd	eƒed
dƒgZdS )ÚPROFIsafeStatusCRCSeedz*PROFISafe Status Message with F_CRC_Seed=1rc   rd   c                 C   s   |   ¡ S r*   rš   ro   r'   r'   r(   rl   J  r[   zPROFIsafeStatusCRCSeed.<lambda>rp   Ústatusr   rr   rœ   N)	r@   rA   rB   r`   r   r   Úprofisafe_status_flagsr   rD   r'   r'   r'   r(   rž   F  s   ÿürž   c                   @   sH   e Zd Zdgej Zdd„ Zdd„ Zdd„ Zedd	„ ƒZ	ed
d„ ƒZ
dS )Ú	PROFIsaferf   c                 C   s   t jS r*   r^   r_   r'   r'   r(   r;   S  s    zPROFIsafe.guess_payload_classc                 C   s   t dƒ‚dS r“   r   r”   r'   r'   r(   r�   V  s    ÿzPROFIsafe.get_data_lengthc                 C   s   dS )NrQ   r'   r”   r'   r'   r(   r–   \  s    z"PROFIsafe.get_mandatory_fields_lenc                   C   s   dS )Nr|   r'   r'   r'   r'   r(   r˜   `  s    zPROFIsafe.get_max_data_lengthc                    s4   |   ¡ ˆ ksJ ‚td | jˆ ¡| fd‡ fdd„iƒS )Nz{}Len{}r�   c                    s   ˆ S r*   r'   r‹   ©Údata_lengthr'   r(   rl   l  r[   z1PROFIsafe.build_PROFIsafe_class.<locals>.<lambda>)r˜   rF   rŽ   r@   )rU   r£   r'   r¢   r(   Úbuild_PROFIsafe_classe  s    ÿýzPROFIsafe.build_PROFIsafe_classN)r@   rA   rB   r   r�   r;   r�   r–   r‘   r˜   r¤   r'   r'   r'   r(   r¡   P  s   
r¡   c                   @   s8   e Zd ZdZedddd„ d�eddd	eƒed
dƒgZdS )ÚPROFIsafeControlz+PROFISafe Control Message with F_CRC_Seed=0rc   rd   c                 C   s   |   ¡ S r*   rš   ro   r'   r'   r(   rl   u  r[   zPROFIsafeControl.<lambda>rp   r›   r   rr   rœ   N)	r@   rA   rB   r`   r   r   r�   r   rD   r'   r'   r'   r(   r¥   q  s   ÿür¥   c                   @   s8   e Zd ZdZedddd„ d�eddd	eƒed
dƒgZdS )ÚPROFIsafeStatusz*PROFISafe Status Message with F_CRC_Seed=0rc   rd   c                 C   s   |   ¡ S r*   rš   ro   r'   r'   r(   rl     r[   zPROFIsafeStatus.<lambda>rp   rŸ   r   rr   rœ   N)	r@   rA   rB   r`   r   r   r    r   rD   r'   r'   r'   r(   r¦   {  s   ÿür¦   ).r†   Zscapy.compatr   Zscapy.errorr   Zscapy.configr   Zscapy.packetr   r   Zscapy.layers.l2r   Zscapy.layers.inetr	   Zscapy.fieldsr
   r   r   r   r   r   r   r   r   r   r   r   Zscapy.libs.sixZlibsr0   r#   r)   r3   r4   rˆ   rI   rb   r9   r�   r    r’   r™   rž   r¡   r¥   r¦   r'   r'   r'   r(   Ú<module>   sP   8ò
r

!
