import ipaddress, subprocess, sys, getopt,dbm
from configparser import ConfigParser
import urllib.request,urllib.parse
+import logging,os.path,time
class DyndnsNetwork(object):
"""
This class represents dynamic DNS server and network.
self.hostname = config_section['hostname']
self.network = ipaddress.ip_network(config_section['network'])
self.server = config_section['server']
- if user in config_section:
+ if 'user' in config_section:
self.user=config_section["user"]
self.password=config_section["password"]
Raises HTTPError if something goes wrong
"""
#construct opener
- if hasattr(self,user):
+ logging.debug("Going to send message to %s",self.server)
+ if hasattr(self,'user'):
password_mgr =urllib.request.HTTPPasswordMgrWithDefaultRealm()
password_mgr.add_password(None,self.server,self.user,self.password)
handler=urllib.request.HTTPBasicAuthHandler(password_mgr)
def get_current_addresses():
result=[]
+ logging.debug("Acquire current IPs")
for line in subprocess.run(['ip','-o','addr','show'],check=True,stdout=subprocess.PIPE).stdout.decode('utf-8').split("\n"):
if not len(line):
continue
if address.is_loopback or address.is_link_local:
continue
result.append(address)
+ logging.debug("Got following addresses: %s",repr(result))
return result
def check_for_update():
addrlist=get_current_addresses()
old_addr=ipaddress.ip_address(database[name].decode("utf-8"))
if old_addr==a:
# Nothing changed go, to next net
+ logging.debug("Address for net %s not changed",name)
break
# address changed
try:
+ logging.info("Doing update for net %s with address %s",name, str(a))
net.nsupdate(a)
database[name]=str(a)
except urllib.error.HTTPError as e:
- pass
+ logging.exception("Http error doing nsupdate code %s",e.code)
break
if not found:
+ logging.info("Address for net %s no more found",name)
del data[name]
-
-
-
config=ConfigParser()
-config['dyngo']={'interval':'60','database':'/var/lib/dyngo/dyngo.db','ca':'/etc/ssl/certs'}
+config['dyngo']={'interval':'60','database':'/var/lib/dyngo/dyngo.db',
+ 'ca':'/etc/ssl/certs','loglevel':'WARNING'}
options=dict(getopt.getopt(sys.argv,"f:")[0])
if not '-f' in options:
options["-f"]="/etc/dyngo.conf"
if len(config.read(options["-f"]))!=1:
print("Cannot read config %s"%options["-f"],file=sys.stderr)
sys.exit(1)
-
conf=config['dyngo']
+logging.basicConfig(format="%(asctime)s %(message)s",
+ level=getattr(logging,conf['loglevel'].upper()))
interval=int(conf['interval'])
database=dbm.open(conf['database'],"c")
https_params={}
for sect in config.sections():
if sect == 'dyngo' or sect == 'DEFAULT':
continue
+ logging.debug("Processing network %s",sect)
networks[sect]=DyndnsNetwork(config[sect])
# Remove stale items from persistent database, which are no more
# mentioned in the config file
-for i in set([x.decode("utf-8") for x in database.keys()])-set(network.keys()):
+for i in set([x.decode("utf-8") for x in database.keys()])-set(networks.keys()):
+ logging.info("Removing from persistent state network %s which is no more in config",i)
del database[i]
-
while True:
check_for_update()
time.sleep(interval)