#!/usr/bin/perl # # Module: vyatta-dns-forwarding.pl # # **** License **** # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # This code was originally developed by Vyatta, Inc. # Portions created by Vyatta are Copyright (C) 2008 Vyatta, Inc. # All Rights Reserved. # # Author: Mohit Mehta # Date: August 2008 # Description: Script to glue Vyatta CLI to dnsmasq daemon # # **** End License **** # use lib "/opt/vyatta/share/perl5/"; use Vyatta::Config; use Vyatta::Misc; use Getopt::Long; use strict; use warnings; my $dnsforwarding_init = '/etc/init.d/dnsmasq'; my $dnsforwarding_conf = '/etc/dnsmasq.conf'; sub dnsforwarding_restart { system("$dnsforwarding_init restart >&/dev/null"); } sub dnsforwarding_stop { system("$dnsforwarding_init stop >&/dev/null"); } sub dnsforwarding_get_constants { my $output; my $date = `date`; chomp $date; $output = "#\n# autogenerated by vyatta-dns-forwarding.pl on $date\n#\n"; $output .= "log-facility=/var/log/dnsmasq.log\n"; $output .= "no-poll\n"; system("rm -f /var/log/dnsmasq.log; touch /var/log/dnsmasq.log"); return $output; } sub dnsforwarding_get_values { my $outside_cli = shift; my $output = ''; my $config = new Vyatta::Config; my $use_dnsmasq_conf = 0; my (@listen_interfaces, $cache_size, @use_nameservers, $use_system_nameservers, @use_dhcp_nameservers); $config->setLevel("service dns forwarding"); if ($outside_cli == 1){ $config->{_active_dir_base} = "/opt/vyatta/config/active/"; @listen_interfaces = $config->returnOrigValues("listen-on"); $cache_size = $config->returnOrigValue("cache-size"); @use_nameservers = $config->returnOrigValues("name-server"); $use_system_nameservers = $config->existsOrig("system"); @use_dhcp_nameservers = $config->returnOrigValues("dhcp"); } else { @listen_interfaces = $config->returnValues("listen-on"); $cache_size = $config->returnValue("cache-size"); @use_nameservers = $config->returnValues("name-server"); $use_system_nameservers = $config->exists("system"); @use_dhcp_nameservers = $config->returnValues("dhcp"); } if (@listen_interfaces != 0) { foreach my $interface (@listen_interfaces) { $output .= "interface=$interface\n"; } } if (defined $cache_size) { $output .= "cache-size=$cache_size\n"; } if (@use_nameservers != 0){ $use_dnsmasq_conf = 1; foreach my $cli_nameserver (@use_nameservers) { $output .= "server=$cli_nameserver\t# statically configured\n"; } } if (defined($use_system_nameservers)) { $use_dnsmasq_conf = 1; my $sys_config = new Vyatta::Config; $sys_config->setLevel("system"); my @system_nameservers; if ($outside_cli == 1){ $sys_config->{_active_dir_base} = "/opt/vyatta/config/active/"; @system_nameservers = $sys_config->returnOrigValues("name-server"); } else { @system_nameservers = $sys_config->returnValues("name-server"); } if (@system_nameservers > 0) { foreach my $system_nameserver (@system_nameservers) { $output .= "server=$system_nameserver\t# system\n"; } } } if (@use_dhcp_nameservers != 0) { $use_dnsmasq_conf = 1; foreach my $interface (@use_dhcp_nameservers) { my $dhcp_nameserver_count=`grep nameserver /etc/resolv.conf.dhclient-new-$interface 2>/dev/null | wc -l`; if ($dhcp_nameserver_count > 0) { my @dhcp_nameservers = `grep nameserver /etc/resolv.conf.dhclient-new-$interface`; for my $each_nameserver (@dhcp_nameservers) { my @nameserver = split(/ /, $each_nameserver, 2); my $ns = $nameserver[1]; chomp $ns; $output .= "server=$ns\t# dhcp $interface\n"; } } } } if ($use_dnsmasq_conf == 1) { $output .= "resolv-file=/etc/dnsmasq.conf\n"; } return $output; } sub dnsforwarding_write_file { my ($config) = @_; open(my $fh, '>', $dnsforwarding_conf) || die "Couldn't open $dnsforwarding_conf - $!"; print $fh $config; close $fh; } sub check_nameserver { my $cmd = `grep nameserver /etc/resolv.conf 2>/dev/null | wc -l`; return $cmd; } sub check_system_nameserver { my $config = new Vyatta::Config; $config->setLevel("system"); my @system_nameservers = $config->returnValues("name-server"); return(@system_nameservers); } sub check_dhcp_any_interface { my $config = new Vyatta::Config; $config->setLevel("interfaces ethernet"); my @eths = $config->listNodes("."); foreach my $eth (@eths) { $config->setLevel("interfaces ethernet $eth"); my @addrs = $config->returnOrigValues("address"); foreach my $addr (@addrs) { if (defined $addr && $addr eq "dhcp") { return 1; } } my @vifs = $config->listNodes("vif"); foreach my $vif (@vifs) { $config->setLevel("interfaces ethernet $eth vif $vif"); my @addrs = $config->returnOrigValues("address"); foreach my $addr (@addrs) { if (defined $addr && $addr eq "dhcp") { return 1; } } } } $config->setLevel("interfaces bridge"); my @bridges = $config->listNodes("."); foreach my $bridge (@bridges) { $config->setLevel("interfaces bridge $bridge"); my @addrs = $config->returnOrigValues("address"); foreach my $addr (@addrs) { if (defined $addr && $addr eq "dhcp") { return 1; } } } return 0; } sub check_dhcp_interface { my $interface = shift; if (!Vyatta::Misc::is_dhcp_enabled($interface)) { print "DNS forwarding error: $interface is not using DHCP to get an IP address\n"; return 0; } if (-e "/var/run/vyatta/dhclient/dhclient_release_$interface") { # dhcp released for the interface print "DNS forwarding warning: DHCP lease for $interface has been released by user\n"; } return 1; } # # main # my ($update_dnsforwarding, $stop_dnsforwarding, $system_nameserver, $dhcp_interface, $outside_cli); GetOptions("update-dnsforwarding!" => \$update_dnsforwarding, "stop-dnsforwarding!" => \$stop_dnsforwarding, "system-nameserver!" => \$system_nameserver, "outside-cli!" => \$outside_cli, "dhcp-interface=s" => \$dhcp_interface); if (defined $system_nameserver) { my $system_nameserver_exists = check_system_nameserver(); if ($system_nameserver_exists < 1){ print "DNS forwarding warning: No name-servers set under 'system name-server'\n"; } } if (defined $dhcp_interface) { if (!check_dhcp_interface($dhcp_interface)){ exit 1; } } if (defined $update_dnsforwarding) { my $config; my $vyatta_config = new Vyatta::Config; $vyatta_config->setLevel("service dns forwarding"); my $use_system_nameservers = $vyatta_config->exists("system"); my @use_dhcp_nameservers = $vyatta_config->returnValues("dhcp"); my @use_nameservers = $vyatta_config->returnValues("name-server"); if (!(defined $use_system_nameservers) && (@use_dhcp_nameservers == 0) && (@use_nameservers == 0)) { my $nameserver_exists = check_nameserver(); my $dhcp_enabled_any_interface = check_dhcp_any_interface(); if ($nameserver_exists < 1 && $dhcp_enabled_any_interface == 0){ print "DNS forwarding warning: No name-servers to forward DNS queries\n"; } } my $called_from_outside_cli = 0; if (defined $outside_cli){ $called_from_outside_cli = 1; } $config = dnsforwarding_get_constants(); $config .= dnsforwarding_get_values($called_from_outside_cli); dnsforwarding_write_file($config); dnsforwarding_restart(); } if (defined $stop_dnsforwarding) { dnsforwarding_stop(); } exit 0; # end of file