o
    MHµd%~  ã                   @   sF  d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZddlmZ ddlmZmZ dZdZg d¢Zg d¢Zd	d
gZdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdhdd„Zdd„ Z dd„ Z!dd„ Z"dd„ Z#did!d"„Z$d#d$„ Z%d%d&„ Z&d'd(„ Z'did)d*„Z(d+d,„ Z)ej*d fd-d.„Z+d/d0„ Z,d1d2„ Z-d3d4„ Z.d5d6„ Z/e	 0¡ fd7d8„Z1e	 0¡ fd9d:„Z2d;d<„ Z3d=d>„ Z4d?d@„ Z5dAdB„ Z6dCdD„ Z7dEdF„ Z8dGdH„ Z9dIdJ„ Z:djdKdL„Z;dkdMdN„Z<dOdP„ Z=dldQdR„Z>dSdT„ Z?dUdV„ Z@dWdX„ ZAdYdZ„ ZBd[d\„ ZCd]d^„ ZDd_d`„ ZEdadb„ ZFdmddde„ZGdfdg„ ZHdS )nz"util.py: utility functions for ufwé    )Úprint_functionN)Úreduce)ÚmkstempÚmktempF)ÚtcpÚudpÚipv6ÚespÚahÚigmpÚgre)r   r	   r
   r   r   r   r   c                 C   sŠ   d}zt  | ¡ W n ty   ‚ w z
t  | d¡ d}W n	 ty%   Y nw zt  | d¡ |dkr6d}W |S d}W |S  tyD   Y |S w )z8Get the protocol for a specified port from /etc/servicesÚ r   r   Úany)ÚsocketÚgetservbynameÚ	Exception)ÚportÚproto© r   ú*/usr/lib/python3/dist-packages/ufw/util.pyÚget_services_proto.   s.   ÿÿüýýr   c                 C   s‚   d}d}|   d¡}t|ƒdkr|d }d}||fS t|ƒdkr9|d }|d }|tv r5td| ƒ}t|ƒ‚||fS tdƒ}t|ƒ‚)	zParse port or port and protocolr   ú/é   r   r   é   zInvalid port with protocol '%s'zBad port)ÚsplitÚlenÚportless_protocolsÚ_Ú
ValueError)Úp_strr   r   ÚtmpÚerr_msgr   r   r   Úparse_port_protoH   s    

÷þr"   c                 C   s–   t js	tdƒ dS t| ƒdkst d| ¡sdS |  d¡}zt  t j|d ¡ W n
 t	y1   Y dS w t|ƒdkr:dS t|ƒdkrIt
|d d	ƒsIdS d	S )
zVerifies if valid IPv6 addressz"python does not have IPv6 support.Fé+   z^[a-fA-F0-9:\./]+$r   r   r   r   T)r   Úhas_ipv6Úwarnr   ÚreÚmatchr   Ú	inet_ptonÚAF_INET6r   Ú_valid_cidr_netmask©ÚaddrÚnetr   r   r   Úvalid_address6\   s"   
ÿr.   c                 C   s˜   t | ƒdkst d| ¡sdS |  d¡}zt tj|d ¡ t|d dƒs'W dS W n
 ty2   Y dS w t |ƒdkr;dS t |ƒdkrJt	|d dƒsJdS dS )	zVerifies if valid IPv4 addressé   z^[0-9\./]+$Fr   r   r   r   T)
r   r&   r'   r   r   r(   ÚAF_INETÚ_valid_dotted_quadsr   Úvalid_netmaskr+   r   r   r   Úvalid_address4v   s"   
ÿÿr3   c                 C   s   t | |ƒp	t| |ƒS )z(Verifies if valid cidr or dotted netmask)r*   r1   )ÚnmÚv6r   r   r   r2   �   s   r2   r   c                 C   s<   |dkrt | ƒS |dkrt| ƒS |dkrt| ƒpt | ƒS t‚)zValidate IP addressesÚ6Ú4r   )r.   r3   r   )r,   Úversionr   r   r   Úvalid_addressš   s   r9   c           	      C   s^  g }d}d}t j}|rd}t j}d| v r7|  d¡}|r%|d dkr%|d= n|s6|d dks3|d dkr6|d= n| | ¡ |s`t|ƒd	kr`t|d |ƒr`zt|d |ƒ|d< W n	 ty_   Y nw |d
 }t  	|t  
||¡¡}||d
 krvd}t|ƒd	krœ|d|d  7 }|sœt|ƒ}||krœd||f }t|ƒ |}d}t||ƒs«d| }t|ƒ t‚||fS )zÎConvert address to standard form. Use no netmask for IP addresses. If
       netmask is specified and not all 1's, for IPv4 use cidr if possible,
       otherwise dotted netmask and for IPv6, use cidr.
    Fr7   r6   r   r   Ú128Ú32z255.255.255.255r   r   TzUsing '%s' for address '%s'zInvalid address '%s')r   r0   r)   r   Úappendr   r1   Ú_dotted_netmask_to_cidrr   Ú	inet_ntopr(   Ú_address4_to_networkÚdebugr9   r   )	Úorigr5   r-   Úchangedr8   Ús_typer,   ÚnetworkÚdbg_msgr   r   r   Únormalize_address¦   sN   
€
þ
rF   c                 C   ó
   t | dƒS )z"Opens the specified file read-onlyÚr)Úopen)Úfnr   r   r   Úopen_file_readÝ   ó   
rK   c                 C   s>   t | ƒ}ztƒ \}}W n ty   | ¡  ‚ w || ||dœS )z=Opens the specified file read-only and a tempfile read-write.)rA   Úorignamer    Útmpname)rK   r   r   Úclose)rJ   rA   r    rN   r   r   r   Ú
open_filesâ   s   þrP   c                 C   s†   |dkrdS | st tjdƒ‚tr| tj ¡ krt |¡ dS d}tjd dkr1t	 | t
|dƒ¡}nt	 | |¡}|dkrAt tjdƒ‚dS )	z~Write to the file descriptor and error out of 0 bytes written. Intended
       to be used with open_files() and close_files().r   NzNot a valid file descriptoréÿÿÿÿr   é   Úasciiz"Could not write to file descriptor)ÚOSErrorÚerrnoÚENOENTÚ
msg_outputÚsysÚstdoutÚfilenoÚwriteÚversion_infoÚosÚbytesÚEIO)ÚfdÚoutÚrcr   r   r   Úwrite_to_fileï   s   
ÿrc   Tc                 C   sX   | d   ¡  t  | d ¡ |r#t | d | d ¡ t | d | d ¡ t | d ¡ dS )zuCloses the specified files (as returned by open_files), and update
       original file with the temporary file.
    rA   r    rM   rN   N)rO   r]   ÚshutilÚcopystatÚcopyÚunlink)ÚfnsÚupdater   r   r   Úclose_files  s   rj   c              
   C   sn   t | ƒ ztj| tjtjdd�}W n ty) } zdt|ƒgW  Y d}~S d}~ww | ¡ d }|jt|ƒgS )z!Try to execute the given command.T)rY   ÚstderrÚuniversal_newlinesé   Nr   )	r@   Ú
subprocessÚPopenÚPIPEÚSTDOUTrT   ÚstrÚcommunicateÚ
returncode)ÚcommandÚspÚexra   r   r   r   Úcmd  s   

þ€ÿrx   c              
   C   sp   zt j| t jd�}t j||jd�}W n ty* } zdt|ƒgW  Y d}~S d}~ww | ¡ d }|jt|ƒgS )z#Try to pipe command1 into command2.)rY   )Ústdinrm   Nr   )rn   ro   rp   rY   rT   rr   rs   rt   )Úcommand1Úcommand2Úsp1Úsp2rw   ra   r   r   r   Úcmd_pipe$  s   €ÿr~   c                 C   s€   z| j }W n ty   | }Y nw z| dd¡}W n ty$   |}Y nw tr3t tj¡r3| |¡ n| t	|ƒ¡ |  
¡  dS )zQImplement our own print statement that will output utf-8 when
       appropriate.úutf-8ÚignoreN)Úbufferr   ÚencoderW   ÚinspectÚisclassÚioÚStringIOr[   r^   Úflush)ÚoutputÚsÚwriterra   r   r   r   Ú_print2  s   
ÿÿr‹   c                 C   s>   z
t tjd|  ƒ W n	 ty   Y nw |rt d¡ dS dS )zPrint error message and exitz
ERROR: %s
r   N)r‹   rX   rk   ÚIOErrorÚexit)ra   Údo_exitr   r   r   ÚerrorG  s   ÿÿr�   c                 C   s,   zt tjd|  ƒ W dS  ty   Y dS w )zPrint warning messagez	WARN: %s
N)r‹   rX   rk   rŒ   ©ra   r   r   r   r%   R  s
   ÿr%   c                 C   sT   t r	|tjkr	t }z|rt|d|  ƒ W dS t|d|  ƒ W dS  ty)   Y dS w )zPrint messagez%s
z%sN)rW   rX   rY   r‹   rŒ   )ra   rˆ   Únewliner   r   r   ÚmsgZ  s   ÿr’   c                 C   s4   t rzttjd|  ƒ W dS  ty   Y dS w dS )zPrint debug messagez
DEBUG: %s
N)Ú	DEBUGGINGr‹   rX   rk   rŒ   r�   r   r   r   r@   h  s   ÿýr@   c                 C   s   t |fdd„|  d¡ƒS )z¡
    A word-wrap function that preserves existing line breaks
    and most spaces in the text. Expects that existing line
    breaks are posix newlines (
).
    c              	   S   s<   d| dt | ƒ|  d¡ d t | dd¡d ƒ |k |f S )Nz%s%s%sz 
Ú
r   r   )r   Úrfindr   )ÚlineÚwordÚwidthr   r   r   Ú<lambda>w  s    ÿÿýÿzword_wrap.<locals>.<lambda>ú )r   r   )Útextr˜   r   r   r   Ú	word_wrapq  s   ûrœ   c                 C   rG   )zWord wrap to a specific widthéK   )rœ   )r›   r   r   r   Ú	wrap_text€  rL   rž   c                    s    dd„ ‰ | j ‡ fdd„d� dS )a$  Sorts list of strings into numeric order, with text case-insensitive.
       Modifies list in place.

       Eg:
       [ '80', 'a222', 'a32', 'a2', 'b1', '443', 'telnet', '3', 'http', 'ZZZ']

       sorts to:
       ['3', '80', '443', 'a2', 'a32', 'a222', 'b1', 'http', 'telnet', 'ZZZ']
    c                 S   s   |   ¡ rt| ƒS |  ¡ S ©N)ÚisdigitÚintÚlower)Útr   r   r   r™   �  s    zhuman_sort.<locals>.<lambda>c                    s   ‡ fdd„t  d| ¡D ƒS )Nc                    s   g | ]}ˆ |ƒ‘qS r   r   )Ú.0Úc©Únormr   r   Ú
<listcomp>�  s    z0human_sort.<locals>.<lambda>.<locals>.<listcomp>z([0-9]+))r&   r   )Úkr¦   r   r   r™   �  s    )ÚkeyN)Úsort)Úlstr   r¦   r   Ú
human_sort…  s   
r­   c                 C   s|   zt | ƒ}W n ty   tdƒ‚w tj dt|ƒd¡}tj |¡s(td| ƒ‚t	|ƒ 
¡ d  dd¡d  ¡ d }t |ƒS )zdFinds parent process id for pid based on /proc/<pid>/stat. See
       'man 5 proc' for details.
    zpid must be an integerú/procÚstatúCouldn't find '%s'r   ú)r   )r¡   r   r   r]   ÚpathÚjoinrr   ÚisfilerŒ   rI   Ú	readlinesÚrsplitr   )ÚmypidÚpidÚnameÚppidr   r   r   Úget_ppid“  s   ÿ$r»   c                 C   sþ   zt | ƒ}W n$ ty   tdƒ}t|ƒ Y dS  ty*   tdƒt| ƒ }t|ƒ‚w | dks3|dkr5dS tj 	dt|ƒd¡}tj 
|¡sOtdƒ| }t|ƒ‚zt|ƒ ¡ d  ¡ d }W n tyn   td	ƒ| }t|ƒ‚w td
| ƒ |dkr{dS t|ƒS )z1Determine if current process is running under sshz%Couldn't find pid (is /proc mounted?)Fz!Couldn't find parent pid for '%s'r   r®   r¯   r°   r   z"Could not find executable for '%s'zunder_ssh: exe is '%s'z(sshd)T)r»   rŒ   r   r%   r   rr   r   r]   r²   r³   r´   rI   rµ   r   r@   Ú	under_ssh)r¸   rº   Úwarn_msgr!   r²   Úexer   r   r   r¼   ª  s4   þþr¼   c                 C   s8   d}|rd}t  d| ¡rt| ƒdk st| ƒ|krdS dS )zVerifies cidr netmasksé    é€   ú^[0-9]+$r   FT)r&   r'   r¡   )r4   r5   Únumr   r   r   r*   Ñ  s   $r*   c                 C   sd   |rdS t  d| ¡r0t  d| ¡}t|ƒdkrdS |D ]}|r*t|ƒdk s*t|ƒdkr- dS qdS dS )z.Verifies dotted quad ip addresses and netmasksFz^[0-9]+\.[0-9\.]+$z\.é   r   éÿ   T)r&   r'   r   r   r¡   )r4   r5   ÚquadsÚqr   r   r   r1   Ý  s   ÿþr1   c              
   C   sÔ   d}|rt ‚t| |ƒst ‚d}ztt dt | ¡¡d ƒ}W n ty4   tt dt | ¡¡d ƒ}Y nw d}t	dƒD ]}||? d@ dkrHd}q;|rNd} n|d7 }q;|dkra|dkrat
d| ƒ}t||ƒsht ‚|S )	z@Convert netmask to cidr. IPv6 dotted netmasks are not supported.r   r   ú>LFr¿   r   TrQ   )r   r1   ÚlongÚstructÚunpackr   Ú	inet_atonÚ	NameErrorr¡   Úrangerr   r*   )r4   r5   ÚcidrÚmbitsÚbitsÚ	found_oneÚnr   r   r   r=   ö  s0   
ÿ

r=   c                 C   sŒ   d}|rt ‚t| |ƒst ‚ztdƒ}W n ty   d}Y nw tdƒD ]}|t| ƒk r3|dd| > O }q#t t 	d|¡¡}t
||ƒsDt ‚|S )z<Convert cidr to netmask. IPv6 dotted netmasks not supported.r   r   r¿   r   r/   rÇ   )r   r*   rÈ   rÌ   rÍ   r¡   r   Ú	inet_ntoarÉ   Úpackr1   )rÎ   r5   r4   rÐ   rÒ   r   r   r   Ú_cidr_to_dotted_netmask$  s$   
ÿ€
rÕ   c           	   
   C   s
  d| vr
t dƒ | S |  d¡}t|ƒdkst|d dƒst‚|d }|d }|}t|dƒr2t|dƒ}ztt 	dt
 |¡¡d ƒ}tt 	dt
 |¡¡d ƒ}W n# tyq   tt 	dt
 |¡¡d ƒ}tt 	dt
 |¡¡d ƒ}Y nw ||@ }t
 t d|¡¡}d||f S )	z8Convert an IPv4 address and netmask to a network addressr   z8_address4_to_network: skipping address without a netmaskr   r   Fr   rÇ   ú%s/%s)r@   r   r   r1   r   r*   rÕ   rÈ   rÉ   rÊ   r   rË   rÌ   r¡   rÓ   rÔ   )	r,   r    ÚhostÚorig_nmr4   Ú	host_bitsÚnm_bitsÚnetwork_bitsrD   r   r   r   r?   A  s*   


þr?   c                 C   s¾  dd„ }d| vrt dƒ | S |  d¡}t|ƒdks t|d dƒs"t‚|d }|d }t d	t tj	|¡¡}zt
dƒ}W n tyF   d}Y nw td
ƒD ]"}||| dƒ}tdƒD ]}	|dt||	 ƒ@ d|	 |d  > O }qXqKzt
dƒ}
W n ty   d}
Y nw tdƒD ]}|t|ƒk r”|
dd| > O }
q„||
@ }g }td
ƒD ]}| t||dƒ|d |d d … dƒ¡ qŸt tj	t d	|d |d |d |d |d |d |d |d ¡	¡}d||f S )z8Convert an IPv6 address and netmask to a network addressc                    s$   d  ‡ fdd„t|d ddƒD ƒ¡S )zDecimal to binaryr   c                    s   g | ]
}t ˆ |? d @ ƒ‘qS )r   )rr   )r¤   Úy©rÂ   r   r   r¨   h  ó    z9_address6_to_network.<locals>.dec2bin.<locals>.<listcomp>r   rQ   )r³   rÍ   )rÂ   Úcountr   rÝ   r   Údec2binf  s   $z%_address6_to_network.<locals>.dec2binr   z8_address6_to_network: skipping address without a netmaskr   r   Tr   z>8Hé   é   rm   rÀ   rR   rÃ   é   é   é   rÖ   )r@   r   r   r2   r   rÉ   rÊ   r   r(   r)   rÈ   rÌ   rÍ   r¡   r<   r>   rÔ   )r,   rà   r    Ú	orig_hostÚnetmaskÚunpackedrÙ   ÚirÒ   ÚjrÚ   r-   r¬   rD   r   r   r   Ú_address6_to_networkd  sT   
ÿÿ&ÿÿ€,þÿrë   c           	      C   s^  |  d¡}t|ƒdkst|d |ƒst‚|d }|d }|dks$|dkr&dS | }d|v rD|  d¡}t|ƒdks>t|d |ƒs@t‚|d }|dksL|dkrNdS |r[t|ƒrXt|ƒsZt‚n
t|ƒrct|ƒset‚t||ƒrq|sqt||ƒ}|r‘td||f ƒ  d¡d }td||f ƒ  d¡d }||kS t	d||f ƒ  d¡d }t	d||f ƒ  d¡d }||kS )	z&Determine if address x is in network yr   r   r   r   z0.0.0.0z::TrÖ   )
r   r   r2   r   r.   r3   r*   rÕ   rë   r?   )	Ú
tested_addÚ
tested_netr5   r    ræ   rç   ÚaddressÚorig_networkrD   r   r   r   Ú
in_networkž  s\   

ÿ
ÿÿÿÿûÿÿÿÿrð   c                  C   sH   d} dD ]}t j |d¡} t j | ¡r nd} q| dkr"ttjdƒ‚| S )Nr   )z/sbinz/binz	/usr/sbinz/usr/binz/usr/local/sbinz/usr/local/binÚiptableszCould not find iptables)r]   r²   r³   ÚexistsrT   rU   rV   )r¾   Údr   r   r   Ú_find_system_iptablesÒ  s   rô   c                 C   sT   | du rt ƒ } t| dgƒ\}}|dkrttjd|  ƒ‚t d|¡}t dd|d ¡S )	zReturn iptables versionNz-Vr   zError running '%s'z\sz^vr   r   )rô   rx   rT   rU   rV   r&   r   Úsub)r¾   rb   ra   r    r   r   r   Úget_iptables_versioná  s   rö   c                 C   sê   dd„ }|rt  ¡ dkrttjdƒ‚| du rtƒ } g }d}|  d¡r$d}|td	d	d
�7 }t| d|gƒ\}}|dkr?ttj	|ƒ‚|| |g d¢ƒrL| 
d¡ || |g d¢ƒrY| 
d¡ t| d|gƒ t| d|gƒ\}}|dkrsttj	|ƒ‚|S )z[Return capabilities set for netfilter to support new features. Callers
       must be root.c                 S   s*   | d|g}t || ƒ\}}|dkrdS dS )Nz-Ar   TF)rx   )r¾   ÚchainÚruleÚargsrb   ra   r   r   r   Útest_capñ  s
   
z,get_netfilter_capabilities.<locals>.test_capr   zMust be rootNzufw-caps-testÚ	ip6tableszufw6-caps-testr   )ÚprefixÚdirz-N)ú-mÚ	conntrackú	--ctstateÚNEWrþ   Úrecentz--setz
recent-set)rþ   rÿ   r   r  rþ   r  z--updatez	--secondsÚ30z
--hitcountr6   zrecent-updatez-Fz-X)r]   ÚgetuidrT   rU   ÚEPERMrô   Úendswithr   rx   rV   r<   )r¾   Ú	do_checksrú   Úcapsr÷   rb   ra   r   r   r   Úget_netfilter_capabilitiesî  s,   


r	  c                 C   s  t | ƒ}tƒ }| ¡ D ]}| d¡s| d¡sq| ¡ }|d }|d  d¡d }tƒ }d |d  d¡dd… ¡|d< |d	 |d
< |d  d¡d |d< |d dkrZ|d |d< n|d  d¡d |d< ||vrutƒ ||< g || |< n||| vr�g || |< || |  |¡ q|S )z:Get and parse netstat the output from get_netstat_output()r   r   r   r   ú:rQ   NÚladdrrR   Úuidrã   r   r¸   ú-r¾   )Úget_netstat_outputÚdictÚ
splitlinesÚ
startswithr   r³   r<   )r5   Únetstat_outputró   r–   r    r   r   Úitemr   r   r   Úparse_netstat_output'  s,    
r  c                    s$  d}|r[d}t j |¡sttjd| ƒ‚t|ƒ ¡ D ]5}| ¡ ‰ | ˆ d krOd 	‡ fdd„t
dtˆ d ƒd	ƒD ƒ¡}ˆ d
  ¡ dkrOd|tˆ d
  ¡ dƒf }q|dkrZttjdƒ‚n0t tjtj¡}zt t | ¡ dt d| dd… ¡¡dd… ¡}W n tyŠ   ttjdƒ‚w t||ƒd S )zGet IP address for interfacer   ú/proc/net/if_inet6ú'%s' does not existrã   r
  c                    ó    g | ]}ˆ d  ||d … ‘qS ©r   rÃ   r   ©r¤   ré   ©r    r   r   r¨   [  ó     z"get_ip_from_if.<locals>.<listcomp>r   rÃ   r   Ú80rÖ   râ   úNo such devicei‰  Ú256sNé   é   é   )r]   r²   rò   rT   rU   rV   rI   rµ   r   r³   rÍ   r   r¢   r¡   rŒ   ÚENODEVr   r0   Ú
SOCK_DGRAMrÓ   ÚfcntlÚioctlrZ   rÉ   rÔ   r   rF   )Úifnamer5   r,   Úprocr–   r‰   r   r  r   Úget_ip_from_ifM  s8    ÿ€ÿÿ
ÿÿr(  c              	      sZ  d}d}t | ƒrd}d}n
t| ƒsttjdƒ‚tj |¡s%ttj	d| ƒ‚d}|rzt
|ƒ ¡ D ]H}| ¡ ‰ ˆ d  ¡ }d	 ‡ fd
d„tdtˆ d ƒdƒD ƒ¡}ˆ d  ¡ dkrdd|tˆ d  ¡ dƒf }| |ksrd|v rwt| |dƒrw|} |S q/|S t
|ƒ ¡ D ]*}d	|vr‡q€| d	¡d  ¡ }zt|dƒ}W n	 ty    Y q€w || krª|} |S q€|S )zGet interface for IP addressFz/proc/net/devTr  r  r  r   rã   r
  c                    r  r  r   r  r  r   r   r¨   ‚  r  z"get_if_from_ip.<locals>.<listcomp>r   rÃ   r   r  rÖ   râ   r   )r.   r3   rŒ   rU   r"  r]   r²   rò   rT   rV   rI   rµ   r   Ústripr³   rÍ   r   r¢   r¡   rð   r(  )r,   r5   r'  Úmatchedr–   r&  Útmp_addrÚipr   r  r   Úget_if_from_ipm  sR    ÿ€ òÿür-  c            	   
   C   s  t  d¡} |  ¡  t d¡}tƒ }| D ]n}| |¡sqt j d|d¡}t  	|t j
t jB ¡s.qd}zt  t j d|d¡¡}W n	 tyF   Y nw zt  |¡}W n	 tyW   Y qw |D ]&}zt  t j ||¡¡d }W n	 tys   Y qZw d|t j |¡f ||< qZq|S )zGet inodes of files in /procr®   rÁ   r`   r  r¾   r   rÖ   )r]   Úlistdirr«   r&   Úcompiler  r'   r²   r³   ÚaccessÚF_OKÚR_OKÚreadlinkr   r¯   Úbasename)	Ú
proc_filesÚpatÚinodesré   Úfd_pathÚexe_pathÚdirsrê   Úinoder   r   r   Ú_get_proc_inodesœ  s<   


ÿÿÿûr<  c                 C   s  ddddddddd	d
ddœ}dddddœ}t j d| ¡}t  |t jt jB ¡s(t‚g }d}t|ƒ ¡ }|D ]L}| 	¡ }|s?d}q4|t
||d  dƒ }	|  d¡rRd}	n
|  d¡r\|	d
kr\q4||d   	d¡\}
}||d  }||d  }| |
t
|dƒ|||	f¡ q4|S )z=Read /proc/net/(tcp|udp)[6] file and return a list of tuples ÚESTABLISHEDÚSYN_SENTÚSYN_RECVÚ	FIN_WAIT1Ú	FIN_WAIT2Ú	TIME_WAITÚCLOSEÚ
CLOSE_WAITÚLAST_ACKÚLISTENÚCLOSING)r   r   rR   rÃ   rã   rä   rå   rá   é	   é
   é   r   rR   rå   rH  )Ú
local_addrÚstater  r;  z	/proc/netFTrL  râ   r   ÚNAr   rK  r
  r  r;  )r]   r²   r³   r0  r1  r2  r   rI   rµ   r   r¡   r  r<   )ÚprotocolÚ
tcp_statesÚproc_net_fieldsrJ   r¬   Úskipped_firstÚlinesr–   ÚfieldsrL  r  r   r  r;  r   r   r   Ú_read_proc_net_protocolÁ  sL   öý
rT  c              	      sÐ   d}t ˆ ƒdkr@d‰tdddƒD ]}ˆd ‡ fdd„t|d |dƒD ƒ¡7 ‰qtd ‡fd	d„tdt ˆƒd
ƒD ƒ¡dƒd }|S g ‰‡ fdd„tdddƒD ƒD ]}ˆ tt|dƒƒ¡ qOtd ˆ¡dƒd }|S )zDConvert an address from /proc/net/(tcp|udp)* to a normalized addressr   rá   r   r¿   c                    ó   g | ]
}ˆ |d  |… ‘qS ©r   r   ©r¤   rê   ©Úpaddrr   r   r¨   ö  rÞ   z(convert_proc_address.<locals>.<listcomp>éþÿÿÿr
  c                    s    g | ]}ˆ ||d  …   ¡ ‘qS )rÃ   )r¢   rW  r  r   r   r¨   ø  r  rÃ   Tc                    rU  rV  r   rW  rX  r   r   r¨   ü  rÞ   râ   Ú.F)r   rÍ   r³   rF   r<   rr   r¡   )rY  Ú	convertedré   r   )rY  r    r   Úconvert_proc_addressð  s$   *ÿþþ	ûr]  c              
   C   sæ   t ƒ }ddg}| r|ddg7 }|D ]}zt|ƒ||< W q ty.   td| ƒ}t|ƒ Y qw tƒ }t| ¡ ƒ}| ¡  d}|D ]0}|| D ])\}}	}
}}t	|ƒ}d}t
|ƒ|v r_|t
|ƒ }|d|d	||	f ||
||f 7 }qFq@|S )
z5netstat-style output, without IPv6 address truncationr   r   Útcp6Úudp6z!Could not get statistics for '%s'r   r  z%-5s %-46s %-11s %-5s %-11s %s
z%s:%s)r  rT  r   r   r%   r<  ÚlistÚkeysr«   r]  r¡   )r5   Úproc_net_datar   Úpr½   r7  Ú	protocolsr‰   r  r   r  r;  rL  r,   r¾   r   r   r   r    s8   ý

þùr  c                 C   sV   |du r| S |   d¡r"t| ƒdk r|}|S tj || dd… ¡}|S tj || ¡}|S )zAdd prefix to dirNr   r   r   )r  r   r]   r²   r³   )rý   rü   Únewdirr   r   r   Ú	_findpath&  s   
ýÿrf  c                 C   s4   t jd dk rt | d¡S t | jddd�¡ d¡S )z,Take a string and convert it to a hex stringr   rR   Úhexr   r€   )ÚerrorsrS   )rX   r\   Úcodecsr‚   ÚbinasciiÚhexlifyÚdecode)r‰   r   r   r   Ú
hex_encode4  s   rm  c                 C   s0   t jd dk r| jdd� d¡S t | ¡ d¡S )z,Take a hex string and convert it to a stringr   rR   rg  )Úencodingr   )rX   r\   rl  rj  Ú	unhexlify)Úhr   r   r   Ú
hex_decode=  s   rq  ú/run/ufw.lockc                 C   s$   d}|st | dƒ}t |tj¡ |S )zCreate a blocking lockfileNÚw)rI   r$  ÚlockfÚLOCK_EX)ÚlockfileÚdryrunÚlockr   r   r   Úcreate_lockD  s
   
ry  c                 C   s>   | du rdS zt  | t j¡ |  ¡  W dS  ty   Y dS w )z(Free lockfile created with create_lock()N)r$  rt  ÚLOCK_UNrO   r   )rx  r   r   r   Úrelease_lockM  s   ýr{  )r   )TrŸ   )NT)F)rr  F)IÚ__doc__Ú
__future__r   rj  ri  rU   r$  r…   rƒ   r]   r&   rd   r   rÉ   rn   rX   Ú	functoolsr   Útempfiler   r   r“   rW   Úsupported_protocolsr   Úipv4_only_protocolsr   r"   r.   r3   r2   r9   rF   rK   rP   rc   rj   rx   r~   r‹   r�   r%   rY   r’   r@   rœ   rž   r­   Úgetpidr»   r¼   r*   r1   r=   rÕ   r?   rë   rð   rô   rö   r	  r  r(  r-  r<  rT  r]  r  rf  rm  rq  ry  r{  r   r   r   r   Ú<module>   s†    
7

	'.#:4

9
& /%/#	
	