o
    'yAf,0                     @   s   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
T ddlmZ d dlZedZde_G dd deZdS )	    N   )CLIENT_VERSION)*)_zddns.systemc                   @   s   e Zd ZdZde Zdd Zedd Zdd Z	d	d
 Z
d'ddZdd Zd(ddZdd Zdd Zdd Zdd Zdd Zd)dd Zd!d" Zd#d$ Zd%d& ZdS )*
DDNSSystemza
		The DDNSSystem class adds a layer of abstraction
		between the ddns software and the system.
	zIPFireDDNSUpdater/%sc                 C   s.   || _ i | _|  | _ttd| j  d S )NzRunning on distribution: %s)core_DDNSSystem__addresses_get_distro_identifierdistrologgerdebugr   )selfr    r   0/usr/lib/python3.10/site-packages/ddns/system.py__init__0   s   
zDDNSSystem.__init__c                 C   s,   | j jd}|r|dr|dd  }|S )Nproxyzhttp://   )r   settingsget
startswith)r   r   r   r   r   r   ;   s   zDDNSSystem.proxyc                 C   s   |  |}| ||r|S d S N)_get_local_ip_address_is_usable_ip_address)r   protoZ
ip_addressr   r   r   get_local_ip_addressE   s   
zDDNSSystem.get_local_ip_addressc              
   C   s   | j dkr?|dkr?ztd}| W  d    W S 1 sw   Y  W t ty> } z|jdkr9W Y d }~d S  d }~ww t)Nipfire-2ipv4z/var/ipfire/red/local-ipaddress   )r
   openreadlineIOErrorerrnoNotImplementedError)r   r   fer   r   r   r   L   s   
$
z DDNSSystem._get_local_ip_address
   c                 C   s`   z	| j ||d}W n
 ty   Y dS w |jdksdS td| }|du r)dS |d S )z`
			Sends a request to an external web server
			to determine the current default IP address.
		timeoutN   s   ^Your IP address is: (.*)$r   )send_requestZDDNSNetworkErrorcoderesearchreadgroupdecode)r   urlr'   responsematchr   r   r   _guess_external_ip_address]   s   
z%DDNSSystem._guess_external_ip_addressc                 K   s6   |dkrd}n|dkrd}nt d| j|fi |S )Nipv6z*https://checkip6.dns.lightningwirelabs.comr   z*https://checkip4.dns.lightningwirelabs.comzunknown address family)
ValueErrorr3   )r   familykwargsr0   r   r   r   guess_external_ip_addressr   s   z$DDNSSystem.guess_external_ip_addressGETN   c              
   C   s  |dkr|r|  |}d }d|v rd||f }nd||f }td||f  |r0td|  tjj||d}|rL|rL| ||}	|dd	|	   |d
| j	 |dd | j
rktd| j
  || j
d ttd |j D ]\}
}td|
|f  qwz)tjj||d}ttd|j  |  D ]\}
}td|
|f  q|W S  tjjy } z\ttd|j  |j D ]\}
}td|
|f  q|jdkrt|j|jdv rt|j|jdkrt|j|jdkrt|j|jdkr	t|j|jdkrt|j d }~w tjjyt } zM|jrot|jtjr?|j}|jdkr:t t!|j|jj"dkrHt#|jj"dkrQt$|jj"dkrZt$|jj"dkrct%|jj"dkrot&|j' d }~w t(j)y } z	ttd t*d }~ww ) Nr9   ?z%s&%sz%s?%szSending request (%s): %sz
  data: %s)dataZAuthorizationzBasic %sz
User-AgentZPragmazno-cachezUsing proxy: %sZhttpzRequest header:z  %s: %sr&   z!Response header (Status Code %s):i  )i  i  i  i  i  i  ZCERTIFICATE_VERIFY_FAILEDc   e   o   q   zConnection timeout)+_format_query_argsr   r   urllibZrequestZRequest_make_basic_auth_headerZ
add_headerr/   
USER_AGENTr   Z	set_proxyr   ZheadersitemsZurlopenr*   infoerrorZ	HTTPErrorZhdrsZDDNSRequestErrorreasonZDDNSAuthenticationErrorZDDNSNotFoundZDDNSTooManyRequestsZDDNSInternalServerErrorZDDNSServiceUnavailableErrorZURLError
isinstancesslZSSLErrorZDDNSCertificateErrorZDDNSSSLErrorr!   DDNSResolveErrorZDDNSNetworkUnreachableErrorZDDNSConnectionRefusedErrorZDDNSNoRouteToHostErrorZhostsocketr'   ZDDNSConnectionTimeoutError)r   r0   methodr<   usernamepasswordr'   Z
query_argsZreqZbasic_auth_headerkvZrespr$   r   r   r   r)   |   s   












zDDNSSystem.send_requestc                 C   s>   g }|  D ]\}}d|tj|f }|| qd|S )Nz%s=%s&)rF   rC   parseZquoteappendjoin)r   r<   argsrQ   rR   argr   r   r   rB      s
   
zDDNSSystem._format_query_argsc                 C   s   d||f }t | }|S )Nz%s:%s)base64Z	b64encodeencode)r   rO   rP   Z
authstringr   r   r   rD     s   z"DDNSSystem._make_basic_auth_headerc                 C   s8   z| j | W S  ty   | | | j |< }| Y S w )zC
			Returns the current IP address for
			the given IP protocol.
		)r   KeyError_get_address)r   r   addressr   r   r   get_address  s   zDDNSSystem.get_addressc                 C   sx   | j dkr|dkrd S | jjdd}|dv }d }|s3z| |}W n ty2   ttd Y nw |s:| 	|}|S )Nr   r4   Zguess_external_iptrue)r_   Zyes1zAFalling back to check the IP address with help of a public server)
r
   r   r   r   r   r"   r   Zwarningr   r8   )r   r   Zguess_ipZlocal_ip_addressr   r   r   r\     s   
zDDNSSystem._get_addressc                 C   s4   |dkrd}|D ]}t ||}|du rq dS dS )zt
			Returns True is the local IP address is usable
			for dynamic DNS (i.e. is not a RFC1918 address or similar).
		r   )z^10\.\d+\.\d+\.\d+$z^192\.168\.\d+\.\d+$z#^172\.(1[6-9]|2[0-9]|31)\.\d+\.\d+$z7^100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\.\d+\.\d+$NFT)r+   r2   )r   r   r]   Zmatchesr2   mr   r   r   r   9  s   
z DDNSSystem._is_usable_ip_addressc              
   C   s  g }|d u r	d}n|dkrt j}n|dkrt j}ntd| z	t |d |}W n1 t jyY } z$|jdkr>g W  Y d }~S |jdkrGt||jdkrTg W  Y d }~S  d }~ww |D ],\}}}}}	|t jkrt|	\}
}}}|dkssq\n|t jkr~|	\}
}nq\|
|vr||
 q\|S )Nr   r4   r   zProtocol not supported: %sr=   )	rM   ZAF_INET6ZAF_INETr5   ZgetaddrinfoZgaierrorr!   rL   rU   )r   Zhostnamer   Z	addressesr6   r1   r$   ZsocktypeZ	canonnameZsockaddrr]   ZportZ	flow_infoZscope_idr   r   r   resolveX  sB   






zDDNSSystem.resolvec                 C   s$   |   }|r|S |  }|r|S dS )zM
			Returns a unique identifier for the distribution
			we are running on.
		unknown)_DDNSSystem__parse_os_release!_DDNSSystem__parse_system_release)r   
os_releaseZsystem_releaser   r   r   r	     s   z!DDNSSystem._get_distro_identifierc              
   C   s   zt dd}W n ty  } z|jdkrW Y d}~dS  d}~ww i }|$ | D ]}td|}|du r7q*|d||d< q*W d   n1 sLw   Y  zd| W S  ty`   Y dS w )zl
			Tries to parse /etc/os-release and
			returns a unique distribution identifier
			if the file exists.
		z/etc/os-releaserr   Nz^([A-Z\_]+)=(.*)$r   z%(ID)s-%(VERSION_ID)s)r   r    r!   	readlinesr+   r2   r.   r[   )r   r#   r$   rh   linera   r   r   r   Z__parse_os_release  s,   

zDDNSSystem.__parse_os_releasec              
   C   s   zt dd}W n ty  } z|jdkrW Y d}~dS  d}~ww |# | }td|}|r>d|d W  d   S W d   dS 1 sIw   Y  dS )zp
			Tries to parse /etc/system-release and
			returns a unique distribution identifier
			if the file exists.
		z/etc/system-releaseri   r   Nz^IPFire (\d).(\d+)z	ipfire-%sr   )r   r    r!   r   r+   r2   r.   )r   r#   r$   rk   ra   r   r   r   Z__parse_system_release  s    
"z!DDNSSystem.__parse_system_release)r%   )r9   NNNr:   r   )__name__
__module____qualname____doc__r   rE   r   propertyr   r   r   r3   r8   r)   rB   rD   r^   r\   r   rd   r	   rf   rg   r   r   r   r   r   '   s*    
	


 	
6r   )rY   r+   rK   rM   Zurllib.requestrC   Zurllib.parseZurllib.error__version__r   errorsZi18nr   ZloggingZ	getLoggerr   Z	propagateobjectr   r   r   r   r   <module>   s   
