1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#!/usr/bin/perl
2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# dynamic-dnsmasq.pl - update dnsmasq's internal dns entries dynamically
3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# Copyright (C) 2004  Peter Willis
4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# This program is free software; you can redistribute it and/or modify
6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# it under the terms of the GNU General Public License as published by
7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# the Free Software Foundation; either version 2 of the License, or
8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# (at your option) any later version.
9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# This program is distributed in the hope that it will be useful,
11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# but WITHOUT ANY WARRANTY; without even the implied warranty of
12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# GNU General Public License for more details.
14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# You should have received a copy of the GNU General Public License
16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# along with this program; if not, write to the Free Software
17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# the purpose of this script is to be able to update dnsmasq's dns
20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# records from a remote dynamic dns client.
21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# basic use of this script:
23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# dynamic-dnsmasq.pl add testaccount 1234 testaccount.mydomain.com
24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# dynamic-dnsmasq.pl listen &
25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# this script tries to emulate DynDNS.org's dynamic dns service, so
27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# technically you should be able to use any DynDNS.org client to
28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# update the records here. tested and confirmed to work with ddnsu
29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# 1.3.1. just point the client's host to the IP of this machine,
30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# port 9020, and include the hostname, user and pass, and it should
31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# work.
32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#
33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# make sure "addn-hosts=/etc/dyndns-hosts" is in your /etc/dnsmasq.conf
34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# file and "nopoll" is commented out.
35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatuse strict;
37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatuse IO::Socket;
38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatuse MIME::Base64;
39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatuse DB_File;
40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatuse Fcntl;
41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatmy $accountdb = "accounts.db";
43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatmy $recordfile = "/etc/dyndns-hosts";
44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatmy $dnsmasqpidfile = "/var/run/dnsmasq.pid"; # if this doesn't exist, will look for process in /proc
45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatmy $listenaddress = "0.0.0.0";
46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatmy $listenport = 9020;
47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat# no editing past this point should be necessary
49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatif ( @ARGV < 1 ) {
51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die "Usage: $0 ADD|DEL|LISTUSERS|WRITEHOSTSFILE|LISTEN\n";
52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} elsif ( lc $ARGV[0] eq "add" ) {
53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die "Usage: $0 ADD USER PASS HOSTNAME\n" unless @ARGV == 4;
54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	add_acct($ARGV[1], $ARGV[2], $ARGV[3]);
55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} elsif ( lc $ARGV[0] eq "del" ) {
56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die "Usage: $0 DEL USER\n" unless @ARGV == 2;
57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print "Are you sure you want to delete user \"$ARGV[1]\"? [N/y] ";
58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $resp = <STDIN>;
59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	chomp $resp;
60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ( lc substr($resp,0,1) eq "y" ) {
61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		del_acct($ARGV[1]);
62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} elsif ( lc $ARGV[0] eq "listusers" or lc $ARGV[0] eq "writehostsfile" ) {
64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $fh;
66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ( lc $ARGV[0] eq "writehostsfile" ) {
67ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        	open($fh, ">$recordfile") || die "Couldn't open recordfile \"$recordfile\": $!\n";
68ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       	flock($fh, 2);
69ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       	seek($fh, 0, 0);
70ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       	truncate($fh, 0);
71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        }
72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while ( my ($key, $val) = each %h ) {
73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		my ($pass, $domain, $ip) = split("\t",$val);
74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if ( lc $ARGV[0] eq "listusers" ) {
75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			print "user $key, hostname $domain, ip $ip\n";
76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		} else {
77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			if ( defined $ip ) {
78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				print $fh "$ip\t$domain\n";
79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ( lc $ARGV[0] eq "writehostsfile" ) {
83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		flock($fh, 8);
84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		close($fh);
85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		dnsmasq_rescan_configs();
86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	undef $X;
88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	untie %h;
89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat} elsif ( lc $ARGV[0] eq "listen" ) {
90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	listen_for_updates();
91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub listen_for_updates {
94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $sock = IO::Socket::INET->new(Listen    => 5,
95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		LocalAddr => $listenaddress, LocalPort => $listenport,
96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		Proto     => 'tcp', ReuseAddr => 1,
97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		MultiHomed => 1) || die "Could not open listening socket: $!\n";
98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	$SIG{'CHLD'} = 'IGNORE';
99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while ( my $client = $sock->accept() ) {
100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		my $p = fork();
101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if ( $p != 0 ) {
102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			next;
103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		$SIG{'CHLD'} = 'DEFAULT';
105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		my @headers;
106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		my %cgi;
107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		while ( <$client> ) {
108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			s/(\r|\n)//g;
109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			last if $_ eq "";
110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			push @headers, $_;
111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		foreach my $header (@headers) {
113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			if ( $header =~ /^GET \/nic\/update\?([^\s].+) HTTP\/1\.[01]$/ ) {
114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				foreach my $element (split('&', $1)) {
115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					$cgi{(split '=', $element)[0]} = (split '=', $element)[1];
116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				}
117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			} elsif ( $header =~ /^Authorization: basic (.+)$/ ) {
118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				unless ( defined $cgi{'hostname'} ) {
119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					print_http_response($client, undef, "badsys");
120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					exit(1);
121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				}
122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				if ( !exists $cgi{'myip'} ) {
123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					$cgi{'myip'} = $client->peerhost();
124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				}
125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				my ($user,$pass) = split ":", MIME::Base64::decode($1);
126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				if ( authorize($user, $pass, $cgi{'hostname'}, $cgi{'myip'}) == 0 ) {
127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					print_http_response($client, $cgi{'myip'}, "good");
128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					update_dns(\%cgi);
129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				} else {
130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					print_http_response($client, undef, "badauth");
131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					exit(1);
132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				}
133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				last;
134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		exit(0);
137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return(0);
139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub add_acct {
142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my ($user, $pass, $hostname) = @_;
143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	$X->put($user, join("\t", ($pass, $hostname)));
145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	undef $X;
146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	untie %h;
147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub del_acct {
150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        my ($user, $pass, $hostname) = @_;
151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        $X->del($user);
153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        undef $X;
154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat        untie %h;
155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub authorize {
159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $user = shift;
160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $pass = shift;
161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $hostname = shift;
162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $ip = shift;;
163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $X = tie my %h, "DB_File", $accountdb, O_RDWR|O_CREAT, 0600, $DB_HASH;
164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my ($spass, $shost) = split("\t", $h{$user});
165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ( defined $h{$user} and ($spass eq $pass) and ($shost eq $hostname) ) {
166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		$X->put($user, join("\t", $spass, $shost, $ip));
167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		undef $X;
168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		untie %h;
169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		return(0);
170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	undef $X;
172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	untie %h;
173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return(1);
174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub print_http_response {
177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $sock = shift;
178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $ip = shift;
179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $response = shift;
180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "HTTP/1.0 200 OK\n";
181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my @tmp = split /\s+/, scalar gmtime();
182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "Date: $tmp[0], $tmp[2] $tmp[1] $tmp[4] $tmp[3] GMT\n";
183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "Server: Peter's Fake DynDNS.org Server/1.0\n";
184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "Content-Type: text/plain; charset=ISO-8859-1\n";
185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "Connection: close\n";
186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "Transfer-Encoding: chunked\n";
187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "\n";
188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	#print $sock "12\n"; # this was part of the dyndns response but i'm not sure what it is
189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	print $sock "$response", defined($ip)? " $ip" : "" . "\n";
190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub update_dns {
193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $hashref = shift;
194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my @records;
195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my $found = 0;
196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	# update the addn-hosts file
197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	open(FILE, "+<$recordfile") || die "Couldn't open recordfile \"$recordfile\": $!\n";
198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	flock(FILE, 2);
199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while ( <FILE> ) {
200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if ( /^(\d+\.\d+\.\d+\.\d+)\s+$$hashref{'hostname'}\n$/si ) {
201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			if ( $1 ne $$hashref{'myip'} ) {
202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				push @records, "$$hashref{'myip'}\t$$hashref{'hostname'}\n";
203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				$found = 1;
204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		} else {
206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			push @records, $_;
207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	unless ( $found ) {
210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		push @records, "$$hashref{'myip'}\t$$hashref{'hostname'}\n";
211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	sysseek(FILE, 0, 0);
213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	truncate(FILE, 0);
214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	syswrite(FILE, join("", @records));
215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	flock(FILE, 8);
216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	close(FILE);
217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	dnsmasq_rescan_configs();
218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return(0);
219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatsub dnsmasq_rescan_configs {
222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	# send the HUP signal to dnsmasq
223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if ( -r $dnsmasqpidfile ) {
224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		open(PID,"<$dnsmasqpidfile") || die "Could not open PID file \"$dnsmasqpidfile\": $!\n";
225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		my $pid = <PID>;
226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		close(PID);
227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		chomp $pid;
228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if ( kill(0, $pid) ) {
229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			kill(1, $pid);
230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		} else {
231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			goto LOOKFORDNSMASQ;
232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	} else {
234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		LOOKFORDNSMASQ:
235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		opendir(DIR,"/proc") || die "Couldn't opendir /proc: $!\n";
236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		my @dirs = grep(/^\d+$/, readdir(DIR));
237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		closedir(DIR);
238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		foreach my $process (@dirs) {
239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			if ( open(FILE,"</proc/$process/cmdline") ) {
240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				my $cmdline = <FILE>;
241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				close(FILE);
242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				if ( (split(/\0/,$cmdline))[0] =~ /dnsmasq/ ) {
243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat					kill(1, $process);
244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat				}
245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			}
246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return(0);
249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
250