#! /usr/bin/perl # # resolv.conf merge hook for rdnssd # # $Id: merge-hook.in 585 2008-02-08 15:45:22Z remi $ # ************************************************************************* # * Copyright © 2007 Pierre Ynard. * # * This program is free software: you can redistribute and/or modify * # * it under the terms of the GNU General Public License as published by * # * the Free Software Foundation, versions 2 or 3 of the license. * # * * # * 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. * # * * # * You should have received a copy of the GNU General Public License * # * along with this program. If not, see <http://www.gnu.org/licenses/>. * # ************************************************************************* use strict; # Max number of nameserver options taken into account. Should be as # defined in <resolv.h> my $MAXNS = 3; # This script tries to share available nameserver slots with IPv4 # entries, for example to allow fallback to IPv4 if IPv6 fails. If # there is not enough room for all IPv6 and IPv4 entries, this script # will limit the IPv6 entries it adds to $RDNSS_LIMIT only. my $RDNSS_LIMIT = $MAXNS - 1; my $sysconfdir = '/etc'; my $localstatedir = '/var'; my $resolvconf = "$sysconfdir/resolv.conf"; my $myresolvconf = "$localstatedir/run/rdnssd/resolv.conf"; # Script code # Parse both files to merge open(RESOLV, "< $resolvconf") or die("cannot read $resolvconf: $!\n"); open(RDNSS, "< $myresolvconf") or die("cannot read $myresolvconf: $!\n"); my @dnsv4 = (); my @other = (); my @rdnss = (); while (<RESOLV>) { if (/^nameserver\s+\d+\.\d+\.\d+\.\d+\s*\n$/) { push(@dnsv4, $_); } elsif (/^nameserver\s+[a-fA-F\d:\.]+\s*\n$/) { } else { push(@other, $_); } } close(RESOLV); while (<RDNSS>) { push(@rdnss, $_); } close(RDNSS); # Merge: insert a limited number of IPv6 RDNSS before IPv4 resolvers my $resolv; $resolv .= join("", @other); my $limit = scalar(@rdnss); if (scalar(@rdnss) > $RDNSS_LIMIT) { my $room = $MAXNS - scalar(@dnsv4); if (scalar(@rdnss) > $room) { $limit = ($room > $RDNSS_LIMIT) ? $room : $RDNSS_LIMIT; } } for (my $i = 0; $i < $limit; $i++) { $resolv .= $rdnss[$i]; } $resolv .= join("", @dnsv4); # Write the result open(TMP, "> $resolvconf.tmp") or die("cannot write $resolvconf.tmp: $!\n"); print TMP $resolv; close(TMP); rename("$resolvconf.tmp", "$resolvconf") or die("cannot write $resolvconf: $!\n");