]> www.wagner.pp.ru Git - oss/dyngo.git/blob - dyngo
Initial commit. Actual dyndns request is not implemented yet
[oss/dyngo.git] / dyngo
1 #!/usr/bin/env python3
2 import ipaddress, subprocess, sys, getopt,dbm
3 from configparser import ConfigParser
4 class DyndnsNetwork(object):
5     """
6     This class represents dynamic DNS server and network.
7     It has attributes hostname network server user and password
8     """
9     def __init__(self,config_section):
10         self.hostname = config_section['hostname']
11         self.network = ipaddress.ip_network(config_section['network'])
12         self.server = config_section['server']
13         if user in config_section:
14             self.user=config_section["user"]
15             self.password=config_section["password"]
16
17
18     def contains(self,address):
19         if self.network.prefixlen==0 and address.is_private:
20             return False
21         if self.network.version != address.version:
22             return False
23         return address in self.network
24    def nsupdate(self, address):
25         raise NotImplementedError
26
27 def get_current_addresses():
28     result=[]    
29     for line in subprocess.run(['ip','-o','addr','show'],check=True,stdout=subprocess.PIPE).stdout.decode('utf-8').split("\n"):
30         if not len(line): 
31             continue
32         (no,iface,family,addr,rest)=line.split(maxsplit=4)
33         address=ipaddress.ip_address(addr.split('/')[0])
34         if address.is_loopback or address.is_link_local:
35             continue
36         result.append(address)
37     return result
38 def check_for_update():
39     addrlist=get_current_addresses()
40     for name,net in networks.items():
41         found=False
42         for a in addrlist:
43             if net.contains(a):
44                 found =True
45                 if name in database:
46                     old_addr=ipaddress.ip_address(database[name].decode("utf-8"))
47                     if old_addr==a:
48                         # Nothing changed go, to next net
49                         break
50                 # address changed
51                 net.nsupdate(a)
52                 database[name]=str(a)
53         if not found:
54             del data[name]
55
56             
57
58
59 config=ConfigPaser()
60 config['dyngo']={'interval':'60','database','/var/lib/dyngo/dyngo.db'}
61 options=dict(getopt.getopt(sys.argv,"f:")[0])
62 if not '-f' in options:
63     options["-f"]="/etc/dyngo.conf"
64 if len(config.read(options["-f"]))!=1:
65     print("Cannot read config %s"%options["-f"],file=sys.stderr)
66     sys.exit(1)
67     
68 conf=config['dyngo']
69 interval=int(conf['interval'])
70 database=dbm.open(conf['database'],"c")
71 # Convert all other config sections to DyndnsNetwork objects
72 networks={}
73 for sect in config.sections():
74     if sect == 'dyngo' or sect= 'DEFAULT':
75         continue
76     networks[sect]=DyndnsNetwork(config[sect])
77 # Remove stale items from persistent database, which are no more
78 # mentioned in the config file
79 for i in set([x.decode("utf-8") for x database.keys()])-set(network.keys()):
80     del database[i]
81
82
83 while True:
84     check_for_update()
85     time.sleep(interval)
86