- Timestamp:
- 04/20/22 17:28:23 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/compact-recs.pl
r835 r836 22 22 use strict; 23 23 use warnings; 24 use Getopt::Long; 24 25 25 26 # Taint-safe (ish) voodoo to push "the directory the script is in" into @INC. … … 41 42 42 43 sub usage { 43 die qq(usage: compact-recs.pl netblock pattern 44 netblock the CIDR block to define the A+PTR template on 45 pattern the pattern to define the new A+PTR template with, and 46 to match A+PTR records within the netblock for deletion 44 die qq(usage: compact-recs.pl netblock pattern [--replace [record id]] 45 netblock the CIDR block to define the A+PTR template on 46 pattern the pattern to define the new A+PTR template with, and 47 to match A+PTR records within the netblock for deletion 48 --replace Optional argument to update an existing template if found. 49 A record ID can be specified to match a particular record, 50 or 'all' to forcibly remove all but one in the event of 51 multiple records. If multiple records are found but neither 52 'all' or a specific record ID is specified, an error will be 53 returned and nothing will be changed since there is no 54 guarantee of which record might be replaced. 55 47 56 OR 48 57 compact-recs.pl --batch patternfile 49 58 patternfile should be a file containing a list of netblock-pattern 50 pairs, whitespace separated 59 pairs, whitespace separated. --replace is ignored in this mode. 51 60 52 61 A PTR template record will be created instead of an A+PTR template … … 54 63 the database. 55 64 56 WARNING: Multiple runs willresult in duplicate template records.65 WARNING: Multiple runs may result in duplicate template records. 57 66 ); 67 } 68 69 my $batchmode = 0; 70 my $replace = 0; 71 my $tmpl_msg = ''; 72 73 GetOptions("batch" => \$batchmode, 74 "replace:s" => \&setreplace ); 75 76 sub setreplace { 77 if ($_[1] eq '') { 78 $replace = -1; 79 } else { 80 $replace = $_[1]; 81 } 82 } 83 84 if ($replace && $replace !~ /^(all|-?\d+)$/) { 85 warn "Invalid --replace argument $replace:\n"; 86 usage(); 58 87 } 59 88 … … 70 99 $dnsdb->{logfullname} = ($dnsdb->{logfullname} ? $dnsdb->{logfullname}."/compact-recs.pl" : $dnsdb->{logusername}); 71 100 72 if ($ARGV[0] eq '--batch') { 73 open NBLIST, "<$ARGV[1]"; 101 if ($batchmode) { 102 # --replace not safe for --batch. could arguably support an in-file flag someday? 103 if ($replace) { 104 $replace = 0; 105 warn "--replace not compatible with --batch. Attempting to continue.\n"; 106 } 107 open NBLIST, "<$ARGV[0]"; 74 108 while (<NBLIST>) { 75 109 next if /^#/; … … 94 128 $dbh->{RaiseError} = 1; 95 129 96 my ($zonecidr,$zone,$ploc) = $dbh->selectrow_array("SELECT revnet,rdns_id,default_location FROM revzones WHERE revnet >>= ?", 97 undef, ($cidr) ); 130 my ($zonecidr,$zone,$ploc) = $dbh->selectrow_array( 131 "SELECT revnet,rdns_id,default_location FROM revzones WHERE revnet >>= ?", 132 undef, ($cidr) ); 98 133 if (!$zone) { 99 134 warn "$cidr is not within a zone currently managed here.\n"; … … 102 137 my $soa = $dnsdb->getSOA('n', 'y', $zone); 103 138 my $dparent = $dnsdb->_hostparent($patt) || 0; 139 # Automatically choose new type as A+PTR template if the new pattern's 140 # domain is managed in this instance, or PTR template if not 104 141 my $newtype = ($dparent ? 65283 : 65282); 105 142 106 my ($istmpl) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = ? AND ". 107 "(type=65282 OR type=65283) AND val = ?", undef, ($zone, $cidr) ); 108 if ($istmpl) { 109 print "Template already exists for $cidr, manual cleanup required\n"; 143 my ($tmplcount) = $dbh->selectrow_array("SELECT count(*) FROM records WHERE rdns_id = ? AND ". 144 "(type=65282 OR type=65283) AND val = ?", undef, ($zone, $cidr) ); 145 if ($tmplcount && !$replace) { 146 # Template(s) found, --replace not set 147 print "One or more templates found for $cidr, use --replace [record_id],". 148 " --replace all, or clean up manually.\n"; 149 return; 150 } elsif ($tmplcount > 1 && ($replace eq '0' || $replace eq '-1')) { 151 # Multiple templates found, --replace either not set (==0) or no argument provided (==-1) 152 print "Multiple templates found matching $cidr but no record ID specified with". 153 " --replace. Use --replace with a record ID, use --replace all, or clean up". 154 " manually.\n"; 110 155 return; 111 156 } … … 117 162 # First, clean up the records that match the template. 118 163 my $getsth = $dbh->prepare("SELECT record_id,host,val FROM records ". 119 164 "WHERE (type = 12 OR type > 65000) AND inetlazy(val) << ? AND rdns_id = ?"); 120 165 my $delsth = $dbh->prepare("DELETE FROM records WHERE record_id = ?"); 121 166 $getsth->execute($cidr, $zone); … … 128 173 } 129 174 130 $dbh->do("INSERT INTO records (domain_id, rdns_id, host, type, val, ttl, location) VALUES (?,?,?,?,?,?,?)", 175 my $template_modified = 0; 176 177 if ($replace) { 178 if ($replace eq 'all') { 179 # clear any templates with the same CIDR, and add a new one 180 $dbh->do("DELETE from records WHERE rdns_id = ? AND (type=65282 OR type=65283) AND val = ?", undef, ($zone, $cidr) ); 181 $dbh->do("INSERT INTO records (domain_id, rdns_id, host, type, val, ttl, location) VALUES (?,?,?,?,?,?,?)", 182 undef, ($dparent, $zone, $patt, $newtype, $cidr, $soa->{minttl}, $ploc) ); 183 $template_modified = 1; 184 $tmpl_msg = ", replaced $tmplcount template records"; 185 } else { 186 if ($replace =~ /^\d+$/) { 187 # $replace == [id] -> replace that record ID, error if it doesn't exist or isn't 188 # a template for the specified CIDR. Arguably some stretch on the latter. 189 my ($rechost,$recval,$rectype) = $dbh->selectrow_array( 190 "SELECT host,val,type,record_id FROM records WHERE record_id = ?", 191 undef, $replace); 192 if (($rectype == 65282 || $rectype == 65283) && $recval eq $cidr) { 193 # Do the update if the record specified matches is a suitable template 194 $dbh->do("UPDATE records SET host = ?, type = ?, val = ? WHERE record_id = ?", 195 undef, ($patt, $newtype, $cidr, $replace) ); 196 $template_modified = 1; 197 $tmpl_msg = ", replaced an existing template record"; 198 } else { 199 # Specified record ID isn't a template record, or doesn't match $cidr, or both 200 die "Specified record ID isn't a template for $cidr, skipping:\n". 201 " $replace found: $rechost $typemap{$rectype} $recval\n"; 202 } 203 } else { 204 # $replace == -1 -> replace/update template iff one template is present 205 # (should have errored out earlier if multiple templates are present) 206 my ($rechost,$recval,$rectype,$recid) = $dbh->selectrow_array( 207 "SELECT host,val,type,record_id FROM records WHERE rdns_id = ? AND (type=65282 OR type=65283) AND val = ?", 208 undef, ($zone, $cidr) ); 209 if ($recid) { 210 # Do the update if we've found an existing template with the same CIDR 211 $dbh->do("UPDATE records SET host = ?, type = ?, val = ? WHERE record_id = ?", 212 undef, ($patt, $newtype, $cidr, $recid) ); 213 $template_modified = 1; 214 $tmpl_msg = ", replaced an existing template record"; 215 } else { 216 $dbh->do("INSERT INTO records (domain_id, rdns_id, host, type, val, ttl, location) VALUES (?,?,?,?,?,?,?)", 217 undef, ($dparent, $zone, $patt, $newtype, $cidr, $soa->{minttl}, $ploc) ); 218 $template_modified = 1; 219 } 220 } # $replace -> [id] or $replace == -1 221 } # $replace <> 'all' 222 } else { 223 # $replace == 0 (not set), just insert the new template 224 $dbh->do("INSERT INTO records (domain_id, rdns_id, host, type, val, ttl, location) VALUES (?,?,?,?,?,?,?)", 131 225 undef, ($dparent, $zone, $patt, $newtype, $cidr, $soa->{minttl}, $ploc) ); 132 $dbh->do("UPDATE revzones SET changed='y' WHERE rdns_id = ?", undef, ($zone)); 133 $dbh->do("UPDATE domains SET changed='y' WHERE domain_id = ?", undef, ($dparent)) if $dparent; 134 $dnsdb->_log(rdns_id => $zone, domain_id => $dparent, group_id => 1, 135 entry => "A+PTR and/or PTR records in $cidr matching $patt replaced by $typemap{$newtype} record for $cidr"); 136 137 $dbh->commit; 226 $template_modified = 1; 227 } 228 229 if ($template_modified) { 230 my %logdata = (rdns_id => $zone, domain_id => $dparent, group_id => 1, 231 entry => "A+PTR and/or PTR records in $cidr matching $patt replaced by $typemap{$newtype} record for $cidr"); 232 $dnsdb->_updateserial(%logdata); 233 $dnsdb->_log(%logdata); 234 $dbh->commit; 235 } else { 236 # no need to do push out a null update that just bumps the serial on the zone(s) 237 $dbh->rollback; 238 } 239 138 240 }; 139 241 if ($@) { 140 print " barf: $@\n";242 print "Error(s) encountered: $@\n"; 141 243 $dbh->rollback; 142 244 return; 143 245 } 144 print " complete ($delcnt records)\n"; 246 print " complete (removed $delcnt PTR/A+PTR records"; 247 print $tmpl_msg; 248 print ")\n"; 145 249 } # squashem ()
Note:
See TracChangeset
for help on using the changeset viewer.