Well, regardless, enjoy my script, we use it to make a hosts file that can
be distributed to other dnsmasq servers of for a kind of
replication technique. It does what we want it to, you may have to change
line 24 to point to the correct leases file

On Mon, Dec 20, 2010 at 5:14 PM, Bernard T. Higonnet <bth...@higonnet.net>wrote:

> Justin McAteer wrote:
> > For all of my installations, the list of current leases is stored at:
> > /var/lib/misc/dnsmasq.leases
>
>
> Turns out that in my FreeBSD 8.1 installation, dnsmasq.leases can be
> found in /var/db/ and was exactly what I was looking for.
>
> Thanks!!
> Bernard Higonnet
>
> _______________________________________________
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss@lists.thekelleys.org.uk
> http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
>
#!/usr/bin/python2

import sys
import os
import subprocess
import optparse
import time

class DNSData(object):
    '''
    Dumps DNS Data into a hosts file.
    '''
    def __init__(self, opts):
        self.opts = opts
        self.ips = set()

    def _get_hosts(self):
        '''
        Run the host command on all the addrs...
        No, run nmap...
        No, parse the leases file and then run host on all of the leases
        '''
        hosts = {}
        leases_fn = '/var/lib/misc/dnsmasq.leases'
        for line in open(leases_fn, 'r').readlines():
            self.ips.add(line.split()[2])
        for ip in self.ips:
            h_cmd = ['host', ip]
            out = subprocess.Popen(h_cmd,
                    stdout=subprocess.PIPE).communicate()[0]
            if out.count('not found'):
                self.ips.remove(ip)
                continue
            hosts[out.split()[-1][:-1]] = ip

        return hosts

    def _get_static(self):
        '''
        Parses the dnsmasq configuration and adds all static hosts files to the
        exported hosts file
        '''
        static_lines = []
        addn_hosts = []
        dnsc = '/etc/dnsmasq.conf'
        for line in open(dnsc, 'r').readlines():
            if line.startswith('addn-hosts='):
                addn_hosts.append(line.split('=')[1].strip())
        for addn in addn_hosts:
            if not os.path.isfile(addn):
                continue
            for line in open(addn, 'r').readlines():
                if line.startswith('#'):
                    continue
                static_lines.append(line)
        return static_lines


    def gen_file(self):
        '''
        Generates the string used in the hosts file
        '''
        hosts = self._get_hosts()
        static = self._get_static()
        hfile = ['## Begin Generated Hosts ##\n']
        for host in hosts:
            line = hosts[host] + '\t\t' + host
            hfile.append(line + '\n')

        hfile.append('#  Begin Static Hosts  #\n')

        for host in static:
            hfile.append(host)

        hfile.append('#  End Static Hosts  #\n')
        hfile.append('## End Generated Hosts ##\n')

        return hfile

    def save_hosts(self, hfile):
        '''
        Save the hosts file.
        '''
        if not os.path.isdir(os.path.dirname(self.opts['location'])):
            os.makedirs(os.path.dirname(self.opts['location']))
        open(self.opts['location'], 'w+').writelines(hfile)


    def start_rsync(self):
        '''
        Start the rsync daemon
        '''
        c_path = '/var/tmp/host-sync.conf'
        conf = ['[hosts]\n',
                'path = ' + os.path.dirname(self.opts['location'])  + '\n'
                'read only = yes\n']
        open(c_path, 'w+').writelines(conf)
        r_cmd = 'rsync --daemon --config=/var/tmp/host-sync.conf --port=9426'
        subprocess.call(r_cmd, shell=True)

    def run_daemon(self):
        '''
        Start dnsdump running as a daemon.. Ok, I don't have the pid fork stuff
        in here, run this in the background!
        '''
        self.start_rsync()
        while True:
            self.save_hosts(data.gen_file())
            time.sleep(600)


def datacenter():
    '''
    Returns the datacenter number
    '''
    d_cmd = "ip a | grep 172 | grep brd | awk '{print $2}' | cut -d. -f2"
    return subprocess.Popen(d_cmd,
            shell=True,
            stdout=subprocess.PIPE).communicate()[0][0]

def detect_networks():
    '''
    Parse all of the dnsmasq configuration files
    '''
    dnsc = '/etc/dnsmasq.conf'
    nets = set()
    conf_files = set()
    for line in open(dnsc, 'r').readlines():
        if line.startswith('domain='):
            dom = line.split(',')
            if dom.__len__() > 1:
                nets.add(dom[1])
        elif line.startswith('conf-dir='):
            cdir = line.split('=')[1].strip()
            if os.path.isdir(cdir):
                for fn_ in os.listdir(cdir):
                    if fn_.endswith('.conf'):
                        conf_files.add(os.path.join(cdir, fn_))
    for cfn in conf_files:
        if not os.path.isfile(cfn):
            continue
        for line in open(cfn, 'r').readlines():
            if line.startswith('domain='):
                dom = line.split(',')
                if dom.__len__() > 1:
                    nets.add(dom[1].strip())
    return nets


def parse():
    '''
    Parse the command line arguments
    '''
    parser = optparse.OptionParser()

    parser.add_option('-n',
            '--networks',
            default='',
            dest='networks',
            help='A comma delimited list of ip/mask networks')

    parser.add_option('-l',
            '--location',
            default='/var/tmp/dnsdump/hosts',
            dest='location',
            help='The local location to store the geneared hosts file')

    parser.add_option('-d',
            '--no-detect',
            default=False,
            dest='no_detect',
            action='store_true',
            help='Pass this flag if you wish to disable network'\
            + 'autodetection and just use the networks passed on the command'\
            + 'line.')

    options, args = parser.parse_args()

    opts = {}

    opts['networks'] = set()

    if options.networks:
        opts['networks'].update(options.networks.split(':'))
    else:
        options.no_detect = False
    if not options.no_detect:
        opts['networks'].update(detect_networks())

#    if not options.networks:
#        dc_ = datacenter()
#        networks = '172.DC0.1.0/24:172.DC0.2.0/24:172.DC1.0.0/24:172.DC1.1.0/24:10.DC0.0.0/24:10.DC0.1.0/24:172.DC2.0.0/16:172.DC3.0.0/16:10.DC3.0.0/16:172.DC4.0.0/16'
#        options.networks = networks.replace('DC', dc_)

    opts['location'] = options.location

    return opts

if __name__ == '__main__':
    opts = parse()
    data = DNSData(opts)
    data.run_daemon()

Reply via email to