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