+
        F                        ^ RI t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	H
t
 ]! ^ ^4       U u/ uF  p V ^8  d
   V ^8  d   K  V RbK  	  up tR tR tR+R ltR tR tR	 tR
 tR tR tR tR tR tR tR tR tR tR tR tR tR t R t!R t"R t#R t$R t%R t&R t'R t(R  t)R! t*R" t+R# t,R$ t-R% t.R& t/R' t0R( t1R) t2R* t3R# u up i ),    N)log)FIREWALLD_TEMPDIRFIREWALLD_PIDFILEc                    \        V \        4      '       d   T pM$V '       d   V P                  4       p  \        V 4      pVR8  d   R# V#   \         d:     \        P
                  ! T 4      p L/  \        P                   d    Ru u # i ; ii ; i)zCheck and Get port id from port string or port id using socket.getservbyname

@param port port string or port id
@return Port id if valid, -1 if port can not be found and -2 if port is too big
  )
isinstanceintstrip
ValueErrorsocketgetservbynameerror)port_ids   & 7/usr/lib/python3.14/site-packages/firewall/functions.py	getPortIDr      s     $::<D	d)C U{	J  	**40<< 		s)   A	 	BA--B	BB		Bc                d   \        V \        4      '       g   \        V \        4      '       d   V # \        V \        4      '       g   V P	                  4       '       d   \        V 4      pV^ 8  d   V3# V# V P                  R4      p\        V4      ^8X  d   V^ ,          P	                  4       '       de   V^,          P	                  4       '       dH   \        V^ ,          4      p\        V^,          4      pV^ 8  d   V^ 8  d   W8  d   W3# W8  d   W13# V3# . p\        \        V4      ^ R4       F  p\        RP                  VRV 4      4      pRP                  W%R 4      p\        V4      ^ 8  df   \        V4      pV^ 8  dR   V^ 8  dI   W8  d   VP                  W34       Kv  W8  d   VP                  W134       K  VP                  V34       K  K  K  V^ 8  g   K  VP                  V34       V\        V4      8X  g   K   M	  \        V4      ^8  d   R# \        V4      ^8  d   R# V^ ,          # )a<  Get port range for port range string or single port id

@param ports an integer or port string or port range string
@return Array containing start and end port id for a valid range or -1 if port can not be found and -2 if port is too big for integer input or -1 for invalid ranges or None if the range is ambiguous.
-Nr   )r
   tuplelistr   isdigitr   splitlenrangejoinappend)portsid1splitsid2matchediport2s   &      r   getPortRanger&   5   s    %:eT#:#: %!86M
[[F 6{aF1I--//F1I4E4E4G4Gq	"q	"!8qyz!z!v G3v;2&,-$u:>E"CaxC1H9NNC:.YNNC:.NNC6* %x axv&F## '$ 7|a		W	1:    c                    V R8X  d   R# \        V 4      p\        V\        4      '       d
   V^ 8  d   R# \        V4      ^8X  d
   RV,          # V^ ,          : V: V^,          : 2# )a  Create port and port range string

@param port port or port range int or [int, int]
@param delimiter of the output string for port ranges, default ':'
@return Port or port range string, empty string if port isn't specified, None if port or port range is not valid
 Nz%s)r&   r
   r   r   )r   	delimiter_ranges   && r   portStrr,   p   sY     rz$F&#6A:	V	f}!!9i;;r'   c                    \        V 4      p\        V4      p\        V4      ^8X  d   \        V4      ^8X  d&   \        V^ ,          4      \        V^ ,          4      8H  # \        V4      ^8X  dQ   \        V^ ,          4      \        V^ ,          4      8  d*   \        V^ ,          4      \        V^,          4      8:  d   R# R# \        V4      ^8X  d   \        V4      ^8X  d   \        V^ ,          4      \        V^ ,          4      8  dx   \        V^ ,          4      \        V^,          4      8:  dQ   \        V^,          4      \        V^ ,          4      8  d*   \        V^,          4      \        V^,          4      8:  d   R# R# )   TF)r&   r   r   )r   r   _portr+   s   &&  r   portInPortRanger0      s   E% F
5zQv;!U1X&)F1I*>>>K1%(#y';;%(#y';;  
UqK1%(#y';;%(#y';;%(#y';;%(#y';;r'   c                N   \        V 4      p\        V4      ^8X  d   V^ ,          V^ ,          3p\        \         V4      p\        \        R V4      R R7      p. pV EF  pV^ ,          V^ ,          8:  d)   V^,          V^,          8  d   VP	                  V4       KA  V^ ,          V^ ,          8:  dP   V^,          V^,          8  d;   V^,          V^ ,          8  d&   VP	                  V4       V^ ,          V^,          3pK  V^ ,          V^ ,          8  g   K  V^,          V^,          8  g   K  V^ ,          V^,          8:  g   K  VP	                  V4       V^ ,          V^,          3pEK  	  \        \        R V4      4      pV^ ,          V^,          8X  d   V^ ,          3pV.V3# )zCoalesce a port range with existing list of port ranges

@param new_range tuple/list/string
@param ranges list of tuple/list/string
@return tuple of (list of ranges added after coalescing, list of removed original ranges)
c                 J    \        V 4      ^8X  d   V ^ ,          V ^ ,          3# T # r.   r   xs   &r   <lambda>#coalescePortRange.<locals>.<lambda>   "    c!fkqtQqTl8q8r'   c                     V ^ ,          # r    r5   s   &r   r7   r8          RSTURVr'   keyc                 D    V ^ ,          V ^,          8X  d   V ^ ,          3# T # r;   r<   r5   s   &r   r7   r8           1Q41Q4<1(FQ(Fr'   r&   r   mapsortedr   r   )	new_rangerangescoalesced_range_rangesremoved_rangesr   s   &&    r   coalescePortRangerJ      s    #9-O
?q *1-q/AB,'G8'BG N1q)oa.@E!H.L!!%(A%(*"U1X-"eAh. !!%(.q158<OAq)"eAh."eAh. !!%($Qx);<O' , #FWXNq_Q//*1-/~..r'   c                   \        V 4      p \        V 4      ^8X  d   V ^ ,          V ^ ,          3p \        \         V4      p\        \        R V4      R R7      p. p. pV EF  pV ^ ,          V^ ,          8:  d)   V ^,          V^,          8  d   VP	                  V4       KA  V ^ ,          V^ ,          8:  df   V ^,          V^,          8  dQ   V ^,          V^ ,          8  d<   VP	                  V4       VP	                  V ^,          ^,           V^,          34       K  V ^ ,          V^ ,          8  dg   V ^,          V^,          8  dR   V ^ ,          V^,          8:  d=   VP	                  V4       VP	                  V^ ,          V ^ ,          ^,
          34       EK6  V ^ ,          V^ ,          8  g   EKN  V ^,          V^,          8  g   EKf  VP	                  V4       VP	                  V^ ,          V ^ ,          ^,
          34       VP	                  V ^,          ^,           V^,          34       EK  	  \        \        R V4      4      p\        \        R V4      4      pWC3# )zbreak a port range from existing list of port ranges

@param remove_range tuple/list/string
@param ranges list of tuple/list/string
@return tuple of (list of ranges added after breaking up, list of removed original ranges)
c                 J    \        V 4      ^8X  d   V ^ ,          V ^ ,          3# T # r3   r4   r5   s   &r   r7    breakPortRange.<locals>.<lambda>   r9   r'   c                     V ^ ,          # r;   r<   r5   s   &r   r7   rM      r=   r'   r>   c                 D    V ^ ,          V ^,          8X  d   V ^ ,          3# T # r;   r<   r5   s   &r   r7   rM      rA   r'   c                 D    V ^ ,          V ^,          8X  d   V ^ ,          3# T # r;   r<   r5   s   &r   r7   rM      s     11qtg&D1&Dr'   rB   )remove_rangerF   rH   rI   added_rangesr   s   &&    r   breakPortRangerS      s     -L
<A$Qa9,'G8'BG NL?eAh&<?eAh+F!!%(OuQx'Q%(*Q58+ !!%(a1!4eAh ?@OeAh&Q58+Q58+ !!%(q<?Q+> ?@!_uQx'LOeAh,F!!%(q<?Q+> ?@a1!4eAh ?@1 6 #FWXNDlSTL))r'   c                     \         P                  ! \        V 4      V4      pV#   \         P                   d     R# i ; i)zCheck and Get service name from port and proto string combination using socket.getservbyport

@param port string or id
@param protocol string
@return Service name if port and protocol are valid, else None
N)r   getservbyportr   r   )r   protonames   && r   getServiceNamerX      s<    ##CIu5 K << s    $ ==c                     \         P                  ! \         P                  V 4       R#   \         P                   d     R# i ; i)z[Check IPv4 address.

@param ip address string
@return True if address is valid, else False
FT)r   	inet_ptonAF_INETr   ips   &r   checkIPr^     s8    ,  << s   %) AAc                $    V P                  R4      # )zNormalize the IPv6 address

This is mostly about converting URL-like IPv6 address to normal ones.
e.g. [1234::4321] --> 1234:4321
z[])r   r\   s   &r   normalizeIP6r`     s     88D>r'   c                     \         P                  ! \         P                  \        V 4      4       R#   \         P                   d     R# i ; i)z[Check IPv6 address.

@param ip address string
@return True if address is valid, else False
FT)r   rZ   AF_INET6r`   r   r\   s   &r   checkIP6rc   &  s=    ,r*:;  << s   .2 A
Ac                 :   V P                  R 4      pVR8w  d$   V RV pW^,           R pV'       d	   V'       g   R# MT pRp\        V4      '       g   R# V'       d/   RV9   d   \        V4      #  \        V4      pT^ 8  g   T^ 8  d   R# R#   \         d     R# i ; i)/NF.Tr   )findr^   r   r   r]   indexaddrmaskr$   s   &    r   checkIPnMaskrl   4  s    GGCLE{&5z!)+4   4==$;4= I 1uB	  s   .B BBc                 ,    V P                  \        4      # N)	translateNOPRINT_TRANS_TABLE)rule_strs   &r   stripNonPrintableCharactersrr   M  s    122r'   c                    V P                  R 4      pVR8w  d$   V RV pW^,           R pV'       d	   V'       g   R# MT pRp\        V4      '       g   R# V'       d    \        V4      pT^ 8  g   T^8  d   R# R#   \         d     R# i ; i)re   NFTr   )rg   rc   r   r   rh   s   &    r   checkIP6nMaskrt   Q  s    GGCLE{&5z!)+4   D>>	D	A q5AG  		s   A9 9BBc                      \        V 4      pV^ 8  g   V^8  d   R#  R#   \         d9     \        P                  ! T 4        R#   \        P                   d      R# i ; ii ; i)r   FT)r   r   r   getprotobynamer   )protocolr$   s   & r   checkProtocolrx   h  sm    
M q5AG    	!!(+  || 			s&     A#AAA#AA#c                     V '       d>   V P                  4       '       d   \        V 4      R 8  d   R#  R# V R8X  d   R# V R8w  d   R# R# )i  FNoneTpmtu)r   r   )tcp_mss_clamp_values   &r   checkTcpMssClampr}   x  sJ    &&((&'#- . 	 !F* F*r'   c                ^    V '       d   \        V 4      ^8  d   R# R F  pW9   g   K   R# 	  R# )zCheck interface string

@param interface string
@return True if interface is valid (maximum 16 chars and does not contain ' ', '/', '!', ':', '*'), else False
FT) re   !*r4   )ifacechs   & r   checkInterfacer     s+     CJO"; # r'   c                     \        V \        4      '       g    \        V ^ 4      p V ^ 8  d
   V R8:  d   R# R#   \         d     R# i ; i)r   Fr   Tr
   r   r   vals   &r   checkUINT16r     sH    c3	c1+C axC5L  		   6 AAc                     \        V \        4      '       g    \        V ^ 4      p V ^ 8  d
   V R8:  d   R# R#   \         d     R# i ; i)r   Fl    Tr   r   s   &r   checkUINT32r     sI    c3	c1+C axC:%  		r   c                 ,   \         P                  P                  \        4      '       g   R#  \	        \        R4      ;_uu_ 4       p V P                  4       pRRR4       \         P                  P                  RX,          4      '       g   R#  \	        RT,          R4      ;_uu_ 4       p T P                  4       pRRR4       RX9   d   R# R#   + '       g   i     L~; i  \         d     R# i ; i  + '       g   i     L@; i  \         d     R# i ; i)zmCheck if firewalld is active

@return True if there is a firewalld pid file and the pid is used by firewalld
FrNz/proc/%sz/proc/%s/cmdline	firewalldT)ospathexistsr   openreadline	Exception)fdpidcmdlines      r   firewalld_is_activer     s     77>>+,,#S))R++-C *
 77>>*s*++$s*C00BkkmG 1
 g# *)  10 s_   C CC D (C19D C	C C C.-C.1D	<D D DDc                  *    \         P                  P                  \        4      '       g   \         P                  ! \        R 4       \
        P                  ! RR\        RR7      #   \         d$   p \        P                  ! RT ,          4       h Rp ? ii ; i)i  wtztemp.F)modeprefixdirdeletez#Failed to create temporary file: %sN)
r   r   r   r   mkdirtempfileNamedTemporaryFiler   r   r   )msgs    r   tempFiler     sn    	ww~~/00HH&.**g+<U
 	
  		7#=>s   (A$ 8A$ $B/BBc                      \        V R 4      ;_uu_ 4       pVP                  4       uuRRR4       #   + '       g   i     R# ; i  \         d*   p\        P                  ! RT : RT: 24        Rp?R# Rp?ii ; i)r   NzFailed to read file "": )r   	readlinesr   r   r   )filenamefes   &  r   readfiler     s^    B(C  A;;= !      B		Ha@AABs0   A 1
A A	A A A9A44A9c                      \        V R 4      ;_uu_ 4       pVP                  V4       RRR4       R#   + '       g   i     R# ; i  \         d*   p\        P                  ! RT : RT: 24        Rp?R# Rp?ii ; i)wNzFailed to write to file "r   FT)r   writer   r   r   )r   liner   r   s   &&  r   	writefiler     s^    (C  AGGDM !
  ! 
   		!DEs0   A 2A A	A A A:A55A:c                 R    V R 8X  d   \        RR4      # V R8X  d   \        RR4      # R# )ipv4z/proc/sys/net/ipv4/ip_forwardz1
ipv6z&/proc/sys/net/ipv6/conf/all/forwardingF)r   )ipvs   &r   enable_ip_forwardingr     s/    
f}8%@@	A5IIr'   c                 F    V P                  R R4      P                  RR4      # )_r   znf-conntrack-r)   )replace)modules   &r   get_nf_conntrack_short_namer     s     >>#s#++OR@@r'   c                    \        V 4      pVR8X  g1   VR8X  g*   Ve&   \        V4      ^8X  d   V^ ,          V^,          8  d   VR8X  d    \        P                  ! RV ,          4       R# VR8X  d    \        P                  ! RV ,          4       R# Vf    \        P                  ! RV ,          4       R# \        V4      ^8X  d3   V^ ,          V^,          8  d   \        P                  ! RV ,          4       R# R# )	   z'%s': port > 65535z'%s': port is invalidz'%s': port is ambiguousz'%s': range start >= endFTr	   r   )r&   r   r   debug2)r   r+   s   & r   
check_portr     s    $F"R<>K1fQi!7R<JJ+d23  r\JJ.56
 	 ^JJ0478  [A&)vay"8JJ1D89r'   c                 N    V R 8X  d   \        V4      # V R8X  d   \        V4      # R# r   r   F)rl   rt   r   sources   &&r   check_addressr     s)    
f}F##	V$$r'   c                 N    V R 8X  d   \        V4      # V R8X  d   \        V4      # R# r   )r^   rc   r   s   &&r   check_single_addressr     s(    
f}v	r'   c                     \        V 4      ^8X  dC   R F  pW,          R8w  g   K   R# 	  R F!  pW,          \        P                  9  g   K    R# 	  R# R# )   :FT)r               )r   r.               	   
   r            )r   string	hexdigits)macr$   s   & r   	check_macr   "  sK    
3x6"Av} # ;AvV--- ; r'   c                 N    . pV  F  pW!9  g   K  VP                  V4       K  	  V# rn   )r   )_listoutputr6   s   &  r   uniqifyr   /  s)    F?MM!  Mr'   c                     \         P                  ! RV ,          4      p\        VP                  4       ^ ,          P	                  4       4      p VP                  4        V #   \         d     R# i ; i)zGet parent for pidzps -o ppid -h -p %d 2>/dev/nullN)r   popenr   r   r   closer   )r   r   s   & r   ppid_of_pidr   8  s]    HH6<=!++-"((*+		 J  s   AA A.-A.c                     ^ RI Hp  ^ RIHp \	        \        \        VP                  4       4      4      p^V\        V 4      ,           \        R4      ,           ,
          # )z
iptables limits length of chain to (currently) 28 chars.
The longest chain we create is POST_<policy>_allow,
which leaves 28 - 11 = 17 chars for <policy>.
)POLICY_CHAIN_PREFIX	SHORTCUTS_allow)firewall.core.ipXtablesr   firewall.core.baser   maxrC   r   values)r   r   longest_shortcuts      r   max_policy_name_lenr   C  sE     <,3sI$4$4$678!C(;$<<s8}LMMr'   c                     ^ RI Hp  \        \        \        V P                  4       4      4      p^V\	        R4      ,           ,
          # )z
Netfilter limits length of chain to (currently) 28 chars.
The longest chain we create is POST_<zone>_allow,
which leaves 28 - 11 = 17 chars for <zone>.
r   __allow)r   r   r   rC   r   r   )r   r   s     r   max_zone_name_lenr   P  s7     -3sI$4$4$678!C	N233r'   c                     \        V 4      ^8  g%   \        V 4      \        P                  ! R4      8  d   R# V  F;  pV\        P                  9  g   K  V\        P
                  9  g   K1  VR9  g   K:   R# 	  R# )r.   SC_LOGIN_NAME_MAXFT)rf   r   r   $)r   r   sysconfr   ascii_lettersdigits)usercs   & r   	checkUserr   \  sZ    
4y1}D	BJJ/B$CCV)))&--  r'   c                     \        V \        4      '       d    \        V 4      p V ^ 8  d
   V R8:  d   R# R #   \         d     R # i ; i)FTi)r
   strr   r   )uids   &r   checkUidr   i  sG    #s	c(C axC9$	  		s   5 AAc                     \        V 4      ^8  g   \        V 4      R8  d   R# R F  pW9   g   K   R# 	  V ^ ,          R8w  d   R# R# )r.   i   Fre   T)|
 r4   )commandr   s   & r   checkCommandr  t  sB    
7|a3w<$.=   qzSr'   c                    V P                  R 4      p\        V4      R9  d   R# V^ ,          R8w  d   V^ ,          R	R R8w  d   R# V^,          R	R R8w  d   R# V^,          R	R R8w  d   R# \        V^,          4      ^8  d   R# R# )
r   FrootN_u_r_tT)r   r   r	   )r   r   )contextr!   s   & r   checkContextr	    s    ]]3F
6{& ayFvay~5ay~ay~
6!9~r'   c                 2    R P                  R V  4       4      # )r   c              3   N   "   T F  p\         P                  ! V4      x  K  	  R # 5irn   )shlexquote).0as   & r   	<genexpr>joinArgs.<locals>.<genexpr>  s     1DqEKKNNDs   #%)r   )argss   &r   joinArgsr    s    881D111r'   c                 .    \         P                  ! V 4      # rn   )r  r   )_strings   &r   	splitArgsr    s    ;;wr'   c                 z    ^ RI pVP                  V 4      p VP                  ! V/ VB  R#   \         d     R# i ; i)r   NFT)inspect	signaturebind	TypeError)fcnr  kwr  sigs   &*,  r   wrong_args_for_callabler    sF    
 

C
 C!r   s   + ::)r   )4r   r   os.pathr  r   r   firewall.core.loggerr   firewall.configr   r   r   rp   r   r&   r,   r0   rJ   rS   rX   r^   r`   rc   rl   rr   rt   rx   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r	  r  r  r  )r$   s   0r   <module>r#     s(    	     $ @ 1c]	 Fq3w AtG	 08v<&4,/^1*h23. 	(

<
A(

N	4
&2 S	s   C
C
