Changeset 583


Ignore:
Timestamp:
01/03/14 14:58:09 (10 years ago)
Author:
Kris Deugau
Message:

/trunk

Revise and extend the showrec_arpa_ns hack to optionally cover all
displayed zone names, all displayed records, or both

May still need a little more fixing for complete coverage.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/DNSDB.pm

    r581 r583  
    213213                force_refresh   => 1,
    214214                lowercase       => 0,   # mangle as little as possible by default
    215                 showrec_arpa_ns => 0,   # show formal .arpa zone name instead of logical CIDR on reverse NS records
     215                # show IPs and CIDR blocks as-is for reverse zones.  valid values are
     216                # 'none' (default, show natural IP or CIDR)
     217                # 'zone' (zone name, wherever used)
     218                # 'record' (IP or CIDR values in reverse record lists)
     219                # 'all' (all IP values in any reverse zone view)
     220                showrev_arpa    => 'none',
    216221        );
    217222
     
    243248
    244249  # Several settings are booleans.  Handle multiple possible ways of setting them.
    245   for my $boolopt ('log_failures', 'force_refresh', 'lowercase', 'usecache', 'showrec_arpa_ns') {
     250  for my $boolopt ('log_failures', 'force_refresh', 'lowercase', 'usecache') {
    246251    if ($self->{$boolopt} ne '1' && $self->{$boolopt} ne '0') {
    247252      # true/false, on/off, yes/no all valid.
     
    253258        }
    254259      } else {
    255         warn "Bad $boolopt setting $self->{$boolopt}\n";
    256         $self->{$boolopt} = 1;
     260        warn "Bad $boolopt setting $self->{$boolopt}, using default\n";
     261        $self->{$boolopt} = $defconfig{$boolopt};
    257262      }
    258263    }
     264  }
     265
     266  # Enum-ish option(s)
     267  if (!grep /$self->{showrev_arpa}/, ('none','zone','record','all')) {
     268    warn "Bad showrev_arpa setting $self->{showrev_arpa}, using default\n";
     269    $self->{showrev_arpa} = 'none';
    259270  }
    260271
     
    11361147    # v4 revzone, formal zone name type
    11371148    my $tmpzone = $zone;
     1149    return ('FAIL', "Non-numerics in apparent IPv4 reverse zone name [$tmpzone]")
     1150        if $tmpzone !~ m{^(?:\d+[/-])?[\d\.]+\.in-addr\.arpa\.?$};
    11381151    $tmpzone =~ s/\.in-addr\.arpa\.?//;
    1139     return ('FAIL', "Non-numerics in apparent IPv4 reverse zone name [$tmpzone]") if $tmpzone !~ m{^(?:\d+[/-])?[\d\.]+$};
    11401152
    11411153    # Snag the octet pieces
     
    11851197    }
    11861198
    1187   } elsif ($zone =~ /\.ip6\.arpa$/) {
     1199  } elsif ($zone =~ /\.ip6\.arpa\.?$/) {
    11881200    # v6 revzone, formal zone name type
    11891201    my $tmpzone = $zone;
     1202##fixme:  if-n-when we decide we can support sub-nibble v6 zone names, we'll need to change this segment
     1203    return ('FAIL', "Non-hexadecimals in apparent IPv6 reverse zone name [$tmpzone]")
     1204        if $tmpzone !~ /^[a-fA-F\d\.]+\.ip6\.arpa\.?$/;
    11901205    $tmpzone =~ s/\.ip6\.arpa\.?//;
    1191 ##fixme:  if-n-when we decide we can support sub-nibble v6 zone names, we'll need to change this segment
    1192     return ('FAIL', "Non-hexadecimals in apparent IPv6 reverse zone name") if $tmpzone !~ /^[a-fA-F\d\.]+$/;
    11931206    my @quads = reverse(split(/\./, $tmpzone));
    11941207    $warnmsg .= "Apparent sub-/64 IPv6 reverse zone\n" if $#quads > 15;
     
    11961209    foreach (@quads) {
    11971210      $tmpcidr .= $_;
    1198       $tmpcidr .= ":" if ++$nc % 4 == 0;
     1211      $tmpcidr .= ":" if ++$nc % 4 == 0 && $nc < $#quads;
    11991212    }
    12001213    my $nq = 1 if $nc % 4 != 0;
     
    12031216      $tmpcidr .= "0";
    12041217    }
    1205     $tmpcidr .= ($nq ? '::' : ':')."/$mask";
     1218    # polish it off with trailing ::/mask if this is a CIDR block instead of an IP
     1219    $tmpcidr .= "::/$mask" if $mask != 128;
    12061220  }
    12071221
     
    12151229  }
    12161230  return ('OK', $cidr);
     1231##fixme:  use wantarray() to decide what to return?
    12171232} # done _zone2cidr()
    12181233
     
    13431358      $cfg->{force_refresh}     = $1 if /^force_refresh\s*=\s*([a-z01]+)/i;
    13441359      $cfg->{lowercase}         = $1 if /^lowercase\s*=\s*([a-z01]+)/i;
    1345       $cfg->{showrec_arpa_ns}   = $1 if /^showrec_arpa_ns\s*=\s*([a-z01]+)/i;
     1360      $cfg->{showrev_arpa}      = $1 if /^showrev_arpa\s*=\s*([a-z]+)/i;
    13461361# not supported in dns.cgi yet
    13471362#      $cfg->{templatedir}      = $1 if m{^templatedir\s*=\s*([a-z0-9/_.-]+)}i;
     
    19992014## DNSDB::revName()
    20002015# Return the reverse zone name based on an rDNS ID
    2001 # Takes a database handle and the rDNS ID
     2016# Takes a database handle and the rDNS ID, and an optional flag to force return of the CIDR zone
     2017# instead of the formal .arpa zone name
    20022018# Returns the reverse zone name or undef on failure
    20032019sub revName {
     
    20062022  my $dbh = $self->{dbh};
    20072023  my $revid = shift;
     2024  my $cidrflag = shift || 'n';
    20082025  my ($revname) = $dbh->selectrow_array("SELECT revnet FROM revzones WHERE rdns_id=?", undef, ($revid) );
    20092026  $errstr = $DBI::errstr if !$revname;
     2027  my $tmp = new NetAddr::IP $revname;
     2028  $revname = _ZONE($tmp, 'ZONE', 'r', '.').($tmp->{isv6} ? '.ip6.arpa' : '.in-addr.arpa')
     2029        if ($self->{showrev_arpa} eq 'zone' || $self->{showrev_arpa} eq 'all') && $cidrflag eq 'n';
    20102030  return $revname if $revname;
    20112031} # end revName()
     
    20612081  my $self = shift;
    20622082  my $dbh = $self->{dbh};
    2063   my $zone = NetAddr::IP->new(shift);
     2083  my $zone = shift;
     2084
     2085  # Autodetect formal .arpa zones
     2086  if ($zone =~ /\.arpa\.?$/) {
     2087    my $code;
     2088    ($code,$zone) = _zone2cidr($zone);
     2089    return ('FAIL', $zone) if $code eq 'FAIL';
     2090  }
     2091  $zone = NetAddr::IP->new($zone);
    20642092
    20652093  return ('FAIL',"Zone name must be a valid CIDR netblock") unless ($zone && $zone->addr !~ /^0/);
     
    22652293    $sql = "SELECT count(*) FROM revzones".
    22662294        " WHERE group_id IN ($args{curgroup}".($args{childlist} ? ",$args{childlist}" : '').")".
    2267         ($args{startwith} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '').
    2268         ($args{filter} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '');
     2295        ($args{startwith} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '');
     2296#    if ($self->{showrev_arpa} eq 'zone' || $self->{showrev_arpa} eq 'all') {
     2297      # Just In Case the UI is using formal .arpa notation, and someone enters something reversed,
     2298      # we want to match both the formal and natural zone name
     2299      $sql .= ($args{filter} ? " AND (CAST(revnet AS VARCHAR) ~* ? OR CAST(revnet AS VARCHAR) ~* ?)" : '');
     2300      push @filterargs, join('[.]',reverse(split(/\[\.\]/,$args{filter}))) if $args{filter};
     2301#    } else {
     2302#      $sql .= ($args{filter} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '');
     2303#    }
    22692304  }
    22702305  my ($count) = $dbh->selectrow_array($sql, undef, @filterargs);
     
    23202355        " INNER JOIN groups ON revzones.group_id=groups.group_id".
    23212356        " WHERE revzones.group_id IN ($args{curgroup}".($args{childlist} ? ",$args{childlist}" : '').")".
    2322         ($args{startwith} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '').
    2323         ($args{filter} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '');
     2357        ($args{startwith} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '');
     2358#    if ($self->{showrev_arpa} eq 'zone' || $self->{showrev_arpa} eq 'all') {
     2359      # Just In Case the UI is using formal .arpa notation, and someone enters something reversed,
     2360      # we want to match both the formal and natural zone name
     2361      $sql .= ($args{filter} ? " AND (CAST(revnet AS VARCHAR) ~* ? OR CAST(revnet AS VARCHAR) ~* ?)" : '');
     2362      push @filterargs, join('[.]',reverse(split(/\[\.\]/,$args{filter}))) if $args{filter};
     2363#    } else {
     2364#      $sql .= ($args{filter} ? " AND CAST(revnet AS VARCHAR) ~* ?" : '');
     2365#    }
    23242366  }
    23252367  # A common tail.
     
    23282370        " OFFSET ".$args{offset}*$self->{perpage});
    23292371
    2330   my $ret = $dbh->selectall_arrayref($sql, { Slice => {} }, @filterargs);
    2331   return $ret;
     2372  my @working;
     2373  my $zsth = $dbh->prepare($sql);
     2374  $zsth->execute(@filterargs);
     2375  while (my $zone = $zsth->fetchrow_hashref) {
     2376    if ($args{revrec} eq 'y' && ($self->{showrev_arpa} eq 'zone' || $self->{showrev_arpa} eq 'all')) {
     2377      my $tmp = new NetAddr::IP $zone->{zone};
     2378      $zone->{zone} = DNSDB::_ZONE($tmp, 'ZONE', 'r', '.').($tmp->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
     2379    }
     2380    push @working, $zone;
     2381  }
     2382  return \@working;
    23322383} # end getZoneList()
    23332384
     
    34913542    if (!$oldsoa) {
    34923543      # old SOA record is missing for some reason.  create a new one.
    3493       my $sql = "INSERT INTO "._rectable($defrec, $revrec)." (group_id, host, type, val, ttl) VALUES (?,?,6,?,?)";
     3544      my $sql = "INSERT INTO "._rectable($defrec, $revrec)." ("._recparent($defrec, $revrec).
     3545        ", host, type, val, ttl) VALUES (?,?,6,?,?)";
    34943546      $dbh->do($sql, undef, ($soa{id}, "$soa{contact}:$soa{prins}",
    34953547        "$soa{refresh}:$soa{retry}:$soa{expire}:$soa{minttl}", $soa{ttl}) );
     
    36323684  push @bindvars, ($args{filter},$args{filter}) if $args{filter};
    36333685
    3634   my $ret = $dbh->selectall_arrayref($sql, { Slice => {} }, (@bindvars) );
    3635   $errstr = "Error retrieving records: ".$dbh->errstr if !$ret;
    3636 
    3637   return $ret;
     3686  my @working;
     3687  my $recsth = $dbh->prepare($sql);
     3688  $recsth->execute(@bindvars);
     3689  while (my $rec = $recsth->fetchrow_hashref) {
     3690    if ($args{revrec} eq 'y' && ($self->{showrev_arpa} eq 'record' || $self->{showrev_arpa} eq 'all')) {
     3691##enhance:  extend {showrev_arpa} eq 'record' to specify record types
     3692      my $tmp = new NetAddr::IP $rec->{val};
     3693      $rec->{val} = DNSDB::_ZONE($tmp, 'ZONE', 'r', '.').($tmp->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
     3694    }
     3695    push @working, $rec;
     3696  }
     3697  return \@working;
    36383698} # end getRecList()
    36393699
     
    37243784
    37253785  # prep for validation
     3786  # Autodetect formal .arpa names
     3787  if ($$val =~ /\.arpa\.?$/) {
     3788    my ($code,$tmpval) = _zone2cidr($$val);
     3789    return ('FAIL', $tmpval) if $code eq 'FAIL';
     3790    $$val = $tmpval;
     3791  }
    37263792  my $addr = NetAddr::IP->new($$val);
    37273793  $$host =~ s/\.+$//;   # FQDNs ending in . are an internal detail, and really shouldn't be exposed in the UI.
  • trunk/dns.cgi

    r581 r583  
    20042004
    20052005  foreach my $rec (@$foo2) {
    2006     # NS records.  Need to do this first before we convert the type-value to the text representation
    2007     if ($rev eq 'y' && $dnsdb->{showrec_arpa_ns} && $rec->{type} == $reverse_typemap{NS}) {
    2008       my $tmp = new NetAddr::IP $rec->{val};
    2009       $rec->{val} = DNSDB::_ZONE($tmp, 'ZONE', 'r', '.').($tmp->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
    2010     }
    20112006    $rec->{type} = $typemap{$rec->{type}};
    20122007    $rec->{fwdzone} = $rev eq 'n';
     
    20342029
    20352030sub fill_recdata {
    2036   $page->param(typelist => $dnsdb->getTypelist($webvar{revrec}, $webvar{type}));
    2037 
    2038 # le sigh.  we may get called with many empty %webvar keys
     2031  # le sigh.  we may get called with many empty %webvar keys
    20392032  no warnings qw( uninitialized );
    20402033
     
    20422035# prefill <domain> or DOMAIN in "Host" space for new records
    20432036  if ($webvar{revrec} eq 'n') {
     2037    $page->param(typelist => $dnsdb->getTypelist($webvar{revrec}, $webvar{type}));
    20442038    my $domroot = ($webvar{defrec} eq 'y' ? 'DOMAIN' : $dnsdb->domainName($webvar{parentid}));
    20452039    $page->param(name   => ($webvar{name} ? $webvar{name} : $domroot));
     
    20522046    my $domroot = ($webvar{defrec} eq 'y' ? 'ADMINDOMAIN' : ".$dnsdb->{domain}");
    20532047    $page->param(name   => ($webvar{name} ? $webvar{name} : $domroot));
    2054     my $zname = ($webvar{defrec} eq 'y' ? 'ZONE' : $dnsdb->revName($webvar{parentid}));
     2048    my $zname = ($webvar{defrec} eq 'y' ? 'ZONE' : $dnsdb->revName($webvar{parentid}, 'y'));
     2049    my $cidr = new NetAddr::IP $zname;
    20552050    $zname =~ s|\d*/\d+$||;
    20562051    $page->param(address        => ($webvar{address} ? $webvar{address} : $zname));
     2052    $page->param(typelist => $dnsdb->getTypelist($webvar{revrec},
     2053        $webvar{type} || ($cidr->{isv6} ? $reverse_typemap{'AAAA+PTR'} : $reverse_typemap{'A+PTR'})));
    20572054  }
    20582055# retrieve the right ttl instead of falling (way) back to the hardcoded system default
     
    21832180        );
    21842181# probably don't need this, keeping for reference for now
    2185 #  foreach (@$zonelist) {
     2182#  foreach my $rec (@$zonelist) {
    21862183#  }
    21872184  $page->param(domtable => $zonelist);
  • trunk/dnsdb.conf

    r581 r583  
    3838#lowercase = 0
    3939
    40 # Show formal .arpa zone name instead of usual CIDR for reverse zone NS records?
    41 #showrec_arpa_ns = 0
     40# Show formal .arpa zone name instead of the natural IP or CIDR for reverse zone names and records?
     41#showrev_arpa = 0
    4242
    4343## General RPC options
  • trunk/textrecs.cgi

    r581 r583  
    8383  $rec->{val} = "$rec->{distance}  $rec->{weight}  $rec->{port}  $rec->{val}" if $rec->{type} eq 'SRV';
    8484  if ($webvar{revrec} eq 'y') {
    85     if ($dnsdb->{showrec_arpa_ns} && $rec->{type} eq 'NS') {
    86       my $tmp = new NetAddr::IP $rec->{val};
    87       $rec->{val} = DNSDB::_ZONE($tmp, 'ZONE', 'r', '.').($tmp->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
    88     }
    8985    printf "%-16s\t%d\t%s\t%s\n", $rec->{val}, $rec->{ttl}, $rec->{type}, $rec->{host};
    9086  } else {
Note: See TracChangeset for help on using the changeset viewer.