Changeset 594 for branches/stable/cgi-bin
- Timestamp:
- 05/15/13 16:17:00 (12 years ago)
- Location:
- branches/stable
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable
- Property svn:mergeinfo changed
/trunk merged: 518-548,552-553
- Property svn:mergeinfo changed
-
branches/stable/cgi-bin/CustIDCK.pm
r593 r594 34 34 my $custid = shift; 35 35 36 return 1 if $custid =~ /^STAFF$/; 37 return 1 if $custid =~ /^5554242$/; # just in case some later change might block this 38 return 1 if $custid =~ /^\d{7}$/; 39 return 1 if $custid =~ /^\d{10}$/; 36 # hardcoded "OK" custids. 37 return 1 if $custid =~ /^STAFF(?:-\d\d?)?$/; 38 return 1 if $custid =~ /^5554242(?:-\d\d?)?$/; # just in case some later change might block this 39 return 1 if $custid =~ /^\d{7}(?:-\d\d?)?$/; 40 return 1 if $custid =~ /^\d{10}(?:-\d\d?)?$/; 41 42 # Force uppercase for now... 43 $custid =~ tr/a-z/A-Z/; 40 44 41 45 # some example code for a database check … … 66 70 67 71 # We should have a valid DB connection by now. 68 my $sth = $dbh->prepare("SELECT custid FROM custid WHERE custid = '$custid'"); 69 $sth->execute; 72 73 my $hr = $dbh->selectrow_hashref("SELECT custid FROM custid WHERE custid = ?", undef, ($custid) ); 74 my $status = 0; 70 75 if ($dbh->err) { 71 76 $CustIDCK::Error = 1; 72 77 $CustIDCK::ErrMsg = $dbh->errstr(); 73 $sth->finish; 74 $dbh->disconnect; 75 return 0; 78 } else { 79 $status = 1 if ( $hr->{custid} ); 76 80 } 77 my $hr = $sth->fetchrow_hashref();78 my $status = 0;79 $status = 1 if ( $hr->{custid} );80 $sth->finish;81 81 $dbh->disconnect; 82 82 return $status; -
branches/stable/cgi-bin/IPDB.pm
r593 r594 23 23 @ISA = qw(Exporter); 24 24 @EXPORT_OK = qw( 25 %disp_alloctypes %list_alloctypes %def_custids @citylist @poplist @masterblocks 26 %allocated %free %routed %bigfree %IPDBacl %aclmsg 27 &initIPDBGlobals &connectDB &finish &checkDBSanity &allocateBlock &addMaster 28 &deleteBlock &getBlockData &mailNotify 25 %disp_alloctypes %list_alloctypes %def_custids @citylist @poplist 26 %IPDBacl %aclmsg 27 &initIPDBGlobals &connectDB &finish &checkDBSanity 28 &addMaster &touchMaster 29 &listSummary &listMaster &listRBlock &listFree &listPool 30 &getMasterList &getTypeList &getPoolSelect &findAllocateFrom 31 &ipParent &subParent &blockParent &getRoutedCity 32 &allocateBlock &updateBlock &deleteBlock &getBlockData 33 &getNodeList &getNodeName &getNodeInfo 34 &mailNotify 29 35 ); 30 36 … … 32 38 %EXPORT_TAGS = ( ALL => [qw( 33 39 %disp_alloctypes %list_alloctypes %def_custids @citylist @poplist 34 @masterblocks %allocated %free %routed %bigfree %IPDBacl %aclmsg 35 &initIPDBGlobals &connectDB &finish &checkDBSanity &allocateBlock 36 &addMaster &deleteBlock &getBlockData &mailNotify 40 %IPDBacl %aclmsg 41 &initIPDBGlobals &connectDB &finish &checkDBSanity 42 &addMaster &touchMaster 43 &listSummary &listMaster &listRBlock &listFree &listPool 44 &getMasterList &getTypeList &getPoolSelect &findAllocateFrom 45 &ipParent &subParent &blockParent &getRoutedCity 46 &allocateBlock &updateBlock &deleteBlock &getBlockData 47 &getNodeList &getNodeName &getNodeInfo 48 &mailNotify 37 49 )] 38 50 ); … … 46 58 our @citylist; 47 59 our @poplist; 48 our @masterblocks;49 our %allocated;50 our %free;51 our %routed;52 our %bigfree;53 60 our %IPDBacl; 54 61 … … 113 120 } 114 121 115 # Master block list116 $sth = $dbh->prepare("select cidr from masterblocks order by cidr");117 $sth->execute;118 return (undef,$sth->errstr) if $sth->err;119 for (my $i=0; my @data = $sth->fetchrow_array(); $i++) {120 $masterblocks[$i] = new NetAddr::IP $data[0];121 $allocated{"$masterblocks[$i]"} = 0;122 $free{"$masterblocks[$i]"} = 0;123 $bigfree{"$masterblocks[$i]"} = 128; # Larger number means smaller block.124 # Set to 128 to prepare for IPv6125 $routed{"$masterblocks[$i]"} = 0;126 }127 128 122 # Load ACL data. Specific username checks are done at a different level. 129 123 $sth = $dbh->prepare("select username,acl from users"); … … 232 226 # Wrap all the SQL in a transaction 233 227 eval { 234 my $sth = $dbh->prepare("select count(*) from masterblocks where cidr <<= '$cidr'"); 235 $sth->execute; 236 my @data = $sth->fetchrow_array; 237 238 if ($data[0] eq 0) { 228 my ($mexist) = $dbh->selectrow_array("SELECT cidr FROM masterblocks WHERE cidr <<= ?", undef, ($cidr) ); 229 230 if (!$mexist) { 239 231 # First case - master is brand-spanking-new. 240 232 ##fixme: rwhois should be globally-flagable somewhere, much like a number of other things 241 233 ## maybe a db table called "config"? 242 $sth = $dbh->prepare("insert into masterblocks (cidr,rwhois) values ('$cidr','y')"); 243 $sth->execute; 234 $dbh->do("INSERT INTO masterblocks (cidr,rwhois) VALUES (?,?)", undef, ($cidr,'y') ); 244 235 245 236 # Unrouted blocks aren't associated with a city (yet). We don't rely on this 246 237 # elsewhere though; legacy data may have traps and pitfalls in it to break this. 247 238 # Thus the "routed" flag. 248 249 $sth = $dbh->prepare("insert into freeblocks (cidr,maskbits,city,routed)". 250 " values ('$cidr',".$cidr->masklen.",'<NULL>','n')"); 251 $sth->execute; 239 $dbh->do("INSERT INTO freeblocks (cidr,maskbits,city,routed) VALUES (?,?,?,?)", undef, 240 ($cidr, $cidr->masklen, '<NULL>', 'n') ); 252 241 253 242 # If we get here, everything is happy. Commit changes. 254 243 $dbh->commit; 255 244 256 } # new master does not contain existing master(s)245 } # done new master does not contain existing master(s) 257 246 else { 258 247 259 248 # collect the master(s) we're going to absorb, and snag the longest netmask while we're at it. 260 249 my $smallmask = $cidr->masklen; 261 $sth = $dbh->prepare("select cidr as mask from masterblocks where cidr <<= '$cidr'");262 $sth->execute ;250 my $sth = $dbh->prepare("SELECT cidr FROM masterblocks WHERE cidr <<= ?"); 251 $sth->execute($cidr); 263 252 my @cmasters; 264 253 while (my @data = $sth->fetchrow_array) { … … 279 268 280 269 # collect the unrouted free blocks within the new master 281 $sth = $dbh->prepare("select cidr from freeblocks where ". 282 "maskbits>=$smallmask and cidr <<= '$cidr' and routed='n'"); 283 $sth->execute; 270 $sth = $dbh->prepare("SELECT cidr FROM freeblocks WHERE maskbits <= ? AND cidr <<= ? AND routed = 'n'"); 271 $sth->execute($smallmask, $cidr); 284 272 while (my @data = $sth->fetchrow_array) { 285 273 my $freeblock = new NetAddr::IP $data[0]; … … 293 281 294 282 # freeblocks 295 $sth = $dbh->prepare(" delete from freeblocks wherecidr <<= ?");296 my $sth2 = $dbh->prepare(" insert into freeblocks (cidr,maskbits,city,routed) values(?,?,'<NULL>','n')");283 $sth = $dbh->prepare("DELETE FROM freeblocks WHERE cidr <<= ?"); 284 my $sth2 = $dbh->prepare("INSERT INTO freeblocks (cidr,maskbits,city,routed) VALUES (?,?,'<NULL>','n')"); 297 285 foreach my $newblock (@blocklist) { 298 $sth->execute( "$newblock");299 $sth2->execute( "$newblock", $newblock->masklen);286 $sth->execute($newblock); 287 $sth2->execute($newblock, $newblock->masklen); 300 288 } 301 289 302 290 # master 303 $sth = $dbh->prepare("delete from masterblocks where cidr <<= '$cidr'"); 304 $sth->execute; 305 $sth = $dbh->prepare("insert into masterblocks (cidr,rwhois) values ('$cidr','y')"); 306 $sth->execute; 291 $dbh->do("DELETE FROM masterblocks WHERE cidr <<= ?", undef, ($cidr) ); 292 $dbh->do("INSERT INTO masterblocks (cidr,rwhois) VALUES (?,?)", undef, ($cidr, 'y') ); 307 293 308 294 # *whew* If we got here, we likely suceeded. … … 319 305 } 320 306 } # end addMaster 307 308 309 ## IPDB::touchMaster() 310 # Update last-changed timestamp on a master block. 311 sub touchMaster { 312 my $dbh = shift; 313 my $master = shift; 314 315 local $dbh->{AutoCommit} = 0; 316 local $dbh->{RaiseError} = 1; 317 318 eval { 319 $dbh->do("UPDATE masterblocks SET mtime=now() WHERE cidr = ?", undef, ($master)); 320 $dbh->commit; 321 }; 322 323 if ($@) { 324 my $msg = $@; 325 eval { $dbh->rollback; }; 326 return ('FAIL',$msg); 327 } 328 return ('OK','OK'); 329 } # end touchMaster() 330 331 332 ## IPDB::listSummary() 333 # Get summary list of all master blocks 334 # Returns an arrayref to a list of hashrefs containing the master block, routed count, 335 # allocated count, free count, and largest free block masklength 336 sub listSummary { 337 my $dbh = shift; 338 339 my $mlist = $dbh->selectall_arrayref("SELECT cidr AS master FROM masterblocks ORDER BY cidr", { Slice => {} }); 340 341 foreach (@{$mlist}) { 342 my ($rcnt) = $dbh->selectrow_array("SELECT count(*) FROM routed WHERE cidr <<= ?", undef, ($$_{master})); 343 $$_{routed} = $rcnt; 344 my ($acnt) = $dbh->selectrow_array("SELECT count(*) FROM allocations WHERE cidr <<= ?", undef, ($$_{master})); 345 $$_{allocated} = $acnt; 346 my ($fcnt) = $dbh->selectrow_array("SELECT count(*) FROM freeblocks WHERE cidr <<= ?". 347 " AND (routed='y' OR routed='n')", undef, ($$_{master})); 348 $$_{free} = $fcnt; 349 my ($bigfree) = $dbh->selectrow_array("SELECT maskbits FROM freeblocks WHERE cidr <<= ?". 350 " AND (routed='y' OR routed='n') ORDER BY maskbits LIMIT 1", undef, ($$_{master})); 351 ##fixme: should find a way to do this without having to HTMLize the <> 352 $bigfree = "/$bigfree" if $bigfree; 353 $bigfree = '<NONE>' if !$bigfree; 354 $$_{bigfree} = $bigfree; 355 } 356 return $mlist; 357 } # end listSummary() 358 359 360 ## IPDB::listMaster() 361 # Get list of routed blocks in the requested master 362 # Returns an arrayref to a list of hashrefs containing the routed block, POP/city the block is routed to, 363 # allocated count, free count, and largest free block masklength 364 sub listMaster { 365 my $dbh = shift; 366 my $master = shift; 367 368 my $rlist = $dbh->selectall_arrayref("SELECT cidr AS block,city FROM routed WHERE cidr <<= ? ORDER BY cidr", 369 { Slice => {} }, ($master) ); 370 371 foreach (@{$rlist}) { 372 my ($acnt) = $dbh->selectrow_array("SELECT count(*) FROM allocations WHERE cidr <<= ?", undef, ($$_{block})); 373 $$_{nsubs} = $acnt; 374 my ($fcnt) = $dbh->selectrow_array("SELECT count(*) FROM freeblocks WHERE cidr <<= ?". 375 " AND (routed='y' OR routed='n')", undef, ($$_{block})); 376 $$_{nfree} = $fcnt; 377 my ($bigfree) = $dbh->selectrow_array("SELECT maskbits FROM freeblocks WHERE cidr <<= ?". 378 " AND (routed='y' OR routed='n') ORDER BY maskbits LIMIT 1", undef, ($$_{block})); 379 ##fixme: should find a way to do this without having to HTMLize the <> 380 $bigfree = "/$bigfree" if $bigfree; 381 $bigfree = '<NONE>' if !$bigfree; 382 $$_{lfree} = $bigfree; 383 } 384 return $rlist; 385 } # end listMaster() 386 387 388 ## IPDB::listRBlock() 389 # Gets a list of free blocks in the requested parent/master in both CIDR and range notation 390 # Takes a parent/master and an optional flag to look at routed or unrouted blocks, depending 391 # on whether the master is a direct master or a routed block 392 # Returns an arrayref to a list of hashrefs containing the CIDR and range-notation blocks 393 sub listRBlock { 394 my $dbh = shift; 395 my $routed = shift; 396 397 # Snag the allocations for this block 398 my $sth = $dbh->prepare("SELECT cidr,city,type,custid,swip,description". 399 " FROM allocations WHERE cidr <<= ? ORDER BY cidr"); 400 $sth->execute($routed); 401 402 # hack hack hack 403 # set up to flag swip=y records if they don't actually have supporting data in the customers table 404 my $custsth = $dbh->prepare("SELECT count(*) FROM customers WHERE custid = ?"); 405 406 my @blocklist; 407 while (my ($cidr,$city,$type,$custid,$swip,$desc) = $sth->fetchrow_array()) { 408 $custsth->execute($custid); 409 my ($ncust) = $custsth->fetchrow_array(); 410 my %row = ( 411 block => $cidr, 412 city => $city, 413 type => $disp_alloctypes{$type}, 414 custid => $custid, 415 swip => ($swip eq 'y' ? 'Yes' : 'No'), 416 partswip => ($swip eq 'y' && $ncust == 0 ? 1 : 0), 417 desc => $desc 418 ); 419 $row{subblock} = ($type =~ /^.r$/); # hmf. wonder why these won't work in the hash declaration... 420 $row{listpool} = ($type =~ /^.[pd]$/); 421 push (@blocklist, \%row); 422 } 423 return \@blocklist; 424 } # end listRBlock() 425 426 427 ## IPDB::listFree() 428 # Gets a list of free blocks in the requested parent/master in both CIDR and range notation 429 # Takes a parent/master and an optional "routed or unrouted" flag that defaults to unrouted. 430 # Returns an arrayref to a list of hashrefs containing the CIDR and range-notation blocks 431 # Returns some extra flags in the hashrefs for routed blocks, since those can have several subtypes 432 sub listFree { 433 my $dbh = shift; 434 my $master = shift; 435 my $routed = shift || 'n'; 436 437 # do it this way so we can waste a little less time iterating 438 my $sth = $dbh->prepare("SELECT cidr,routed FROM freeblocks WHERE cidr <<= ? AND ". 439 ($routed eq 'n' ? '' : 'NOT')." routed = 'n' ORDER BY cidr"); 440 $sth->execute($master); 441 my @flist; 442 while (my ($cidr,$rtype) = $sth->fetchrow_array()) { 443 $cidr = new NetAddr::IP $cidr; 444 my %row = ( 445 fblock => "$cidr", 446 frange => $cidr->range, 447 ); 448 if ($routed eq 'y') { 449 $row{subblock} = ($rtype ne 'y' && $rtype ne 'n'); 450 $row{fbtype} = $rtype; 451 } 452 push @flist, \%row; 453 } 454 return \@flist; 455 } # end listFree() 456 457 458 ## IPDB::listPool() 459 # 460 sub listPool { 461 my $dbh = shift; 462 my $pool = shift; 463 464 my $sth = $dbh->prepare("SELECT ip,custid,available,description,type". 465 " FROM poolips WHERE pool = ? ORDER BY ip"); 466 $sth->execute($pool); 467 my @poolips; 468 while (my ($ip,$custid,$available,$desc,$type) = $sth->fetchrow_array) { 469 my %row = ( 470 ip => $ip, 471 custid => $custid, 472 available => $available, 473 desc => $desc, 474 delme => $available eq 'n' 475 ); 476 push @poolips, \%row; 477 } 478 return \@poolips; 479 } # end listPool() 480 481 482 ## IPDB::getMasterList() 483 # Get a list of master blocks, optionally including last-modified timestamps 484 # Takes an optional flag to indicate whether to include timestamps; 485 # 'm' includes ctime, all others (suggest 'c') do not. 486 # Returns an arrayref to a list of hashrefs 487 sub getMasterList { 488 my $dbh = shift; 489 my $stampme = shift || 'm'; # optional but should be set by caller for clarity 490 491 my $mlist = $dbh->selectall_arrayref("SELECT cidr AS master".($stampme eq 'm' ? ',mtime' : ''). 492 " FROM masterblocks ORDER BY cidr", { Slice => {} }); 493 return $mlist; 494 } # end getMasterList() 495 496 497 ## IPDB::getTypeList() 498 # Get an alloctype/description pair list suitable for dropdowns 499 # Takes a flag to determine which general groups of types are returned 500 # Returns an reference to an array of hashrefs 501 sub getTypeList { 502 my $dbh = shift; 503 my $tgroup = shift || 'a'; # technically optional, like this, but should 504 # really be specified in the call for clarity 505 my $tlist; 506 if ($tgroup eq 'p') { 507 # grouping 'p' - primary allocation types. These include static IP pools (_d and _p), 508 # dynamic-allocation ranges (_e), containers (_c), and the "miscellaneous" cn, in, and en types. 509 $tlist = $dbh->selectall_arrayref("SELECT type,listname FROM alloctypes WHERE listorder < 500 ". 510 "AND type NOT LIKE '_i' AND type NOT LIKE '_r' ORDER BY listorder", { Slice => {} }); 511 } elsif ($tgroup eq 'c') { 512 # grouping 'c' - contained types. These include all static IPs and all _r types. 513 $tlist = $dbh->selectall_arrayref("SELECT type,listname FROM alloctypes WHERE listorder <= 500 ". 514 " AND (type LIKE '_i' OR type LIKE '_r') ORDER BY listorder", { Slice => {} }); 515 } else { 516 # grouping 'a' - all standard allocation types. This includes everything 517 # but mm (present only as a formality). Make this the default. 518 $tlist = $dbh->selectall_arrayref("SELECT type,listname FROM alloctypes WHERE listorder <= 500 ". 519 " ORDER BY listorder", { Slice => {} }); 520 } 521 return $tlist; 522 } 523 524 525 ## IPDB::getPoolSelect() 526 # Get a list of pools matching the passed city and type that have 1 or more free IPs 527 # Returns an arrayref to a list of hashrefs 528 sub getPoolSelect { 529 my $dbh = shift; 530 my $iptype = shift; 531 my $pcity = shift; 532 533 my ($ptype) = ($iptype =~ /^(.)i$/); 534 return if !$ptype; 535 $ptype .= '_'; 536 537 my $plist = $dbh->selectall_arrayref( 538 "SELECT (SELECT city FROM allocations WHERE cidr=poolips.pool) AS poolcit, ". 539 "poolips.pool AS poolblock, COUNT(*) AS poolfree FROM poolips,allocations ". 540 "WHERE poolips.available='y' AND poolips.pool=allocations.cidr ". 541 "AND allocations.city = ? AND poolips.type LIKE ? ". 542 "GROUP BY pool", { Slice => {} }, ($pcity, $ptype) ); 543 return $plist; 544 } # end getPoolSelect() 545 546 547 ## IPDB::findAllocateFrom() 548 # Find free block to add a new allocation from. (CIDR block version of pool select above, more or less) 549 # Takes 550 # - mask length 551 # - allocation type 552 # - POP city "parent" 553 # - optional master-block restriction 554 # - optional flag to allow automatic pick-from-private-network-ranges 555 # Returns a string with the first CIDR block matching the criteria, if any 556 sub findAllocateFrom { 557 my $dbh = shift; 558 my $maskbits = shift; 559 my $type = shift; 560 my $city = shift; 561 my $pop = shift; 562 my %optargs = @_; 563 564 my $failmsg = "No suitable free block found\n"; 565 566 ## Set up the SQL to find out what freeblock we can (probably) use for an allocation. 567 ## Very large systems will require development of a reserve system (possibly an extension 568 ## of the reserve-for-expansion concept in https://secure.deepnet.cx/trac/ipdb/ticket/24?) 569 ## Also populate a value list for the DBI call. 570 571 my @vallist = ($maskbits, ($type eq 'rm' ? 'n' : ($type =~ /^(.)r$/ ? "$1" : 'y')) ); 572 my $sql = "SELECT cidr FROM freeblocks WHERE maskbits <= ? AND routed = ?"; 573 574 # for PPP(oE) and container types, the POP city is the one attached to the pool. 575 # individual allocations get listed with the customer city site. 576 ##fixme: chain cities to align roughly with a full layer-2 node graph 577 $city = $pop if $type !~ /^.[pc]$/; 578 if ($type ne 'rm' && $city) { 579 $sql .= " AND city = ?"; 580 push @vallist, $city; 581 } 582 # Allow specifying an arbitrary full block, instead of a master 583 if ($optargs{gimme}) { 584 $sql .= " AND cidr >>= ?"; 585 push @vallist, $optargs{gimme}; 586 } 587 # if a specific master was requested, allow the requestor to self->shoot(foot) 588 if ($optargs{master} && $optargs{master} ne '-') { 589 $sql .= " AND cidr <<= ?" if $optargs{master} ne '-'; 590 push @vallist, $optargs{master}; 591 } else { 592 # if a specific master was NOT requested, filter out the RFC 1918 private networks 593 if (!$optargs{allowpriv}) { 594 $sql .= " AND NOT (cidr <<= '192.168.0.0/16' OR cidr <<= '10.0.0.0/8' OR cidr <<= '172.16.0.0/12')"; 595 } 596 } 597 # Sorting and limiting, since we don't (currently) care to provide a selection of 598 # blocks to carve up. This preserves something resembling optimal usage of the IP 599 # space by forcing contiguous allocations and free blocks as much as possible. 600 $sql .= " ORDER BY maskbits DESC,cidr LIMIT 1"; 601 602 my ($fbfound) = $dbh->selectrow_array($sql, undef, @vallist); 603 return $fbfound; 604 } # end findAllocateFrom() 605 606 607 ## IPDB::ipParent() 608 # Get an IP's parent pool's details 609 # Takes a database handle and IP 610 # Returns a hashref to the parent pool block, if any 611 sub ipParent { 612 my $dbh = shift; 613 my $block = shift; 614 615 my $pinfo = $dbh->selectrow_hashref("SELECT cidr,custid,type,city,description FROM allocations". 616 " WHERE cidr >>= ?", undef, ($block) ); 617 return $pinfo; 618 } # end ipParent() 619 620 621 ## IPDB::subParent() 622 # Get a block's parent's details 623 # Takes a database handle and CIDR block 624 # Returns a hashref to the parent container block, if any 625 sub subParent { 626 my $dbh = shift; 627 my $block = shift; 628 629 my $pinfo = $dbh->selectrow_hashref("SELECT cidr,custid,type,city,description FROM allocations". 630 " WHERE cidr >>= ?", undef, ($block) ); 631 return $pinfo; 632 } # end subParent() 633 634 635 ## IPDB::blockParent() 636 # Get a block's parent's details 637 # Takes a database handle and CIDR block 638 # Returns a hashref to the parent container block, if any 639 sub blockParent { 640 my $dbh = shift; 641 my $block = shift; 642 643 my $pinfo = $dbh->selectrow_hashref("SELECT cidr,city FROM routed". 644 " WHERE cidr >>= ?", undef, ($block) ); 645 return $pinfo; 646 } # end blockParent() 647 648 649 ## IPDB::getRoutedCity() 650 # Get the city for a routed block. 651 sub getRoutedCity { 652 my $dbh = shift; 653 my $block = shift; 654 655 my ($rcity) = $dbh->selectrow_array("SELECT city FROM routed WHERE cidr = ?", undef, ($block) ); 656 return $rcity; 657 } # end getRoutedCity() 321 658 322 659 … … 362 699 # and available='y' order by ip limit 1); 363 700 364 # If no specific IP was requested, pick the next available one from the pool. 365 if (!$cidr) { 366 $sth = $dbh->prepare("select ip from poolips where pool='$alloc_from'". 367 " and available='y' order by ip"); 368 $sth->execute; 369 370 my @data = $sth->fetchrow_array; 371 $cidr = $data[0]; # $cidr is already declared when we get here! 372 } 373 374 $sth = $dbh->prepare("update poolips set custid=?,city=?,". 375 "available='n',description=?,notes=?,circuitid=?,privdata=?". 376 " where ip=?"); 377 $sth->execute($custid, $city, $desc, $notes, $circid, $privdata, "$cidr"); 701 if ($cidr) { 702 my ($isavail) = $dbh->selectrow_array("SELECT available FROM poolips WHERE ip=?", undef, ($cidr) ); 703 if ($isavail eq 'n') { 704 die "IP already allocated. Deallocate and reallocate, or update the entry\n"; 705 } 706 if (!$isavail) { 707 die "IP is not in an IP pool.\n"; 708 } 709 } else { 710 ($cidr) = $dbh->selectrow_array("SELECT ip FROM poolips WHERE pool=? AND available='y' ORDER BY ip", 711 undef, ($alloc_from) ); 712 } 713 $dbh->do("UPDATE poolips SET custid=?,city=?,available='n',description=?,notes=?,circuitid=?,privdata=? ". 714 "WHERE ip=?", undef, ($custid, $city, $desc, $notes, $circid, $privdata, $cidr) ); 715 378 716 # node hack 379 717 if ($nodeid && $nodeid ne '') { … … 382 720 } 383 721 # end node hack 722 384 723 $dbh->commit; 385 724 }; 386 725 if ($@) { 387 $msg .= ": '".$sth->errstr."'";726 $msg .= ": $@"; 388 727 eval { $dbh->rollback; }; 389 728 return ('FAIL',$msg); … … 634 973 635 974 975 ## IPDB::updateBlock() 976 # Update an allocation 977 # Takes all allocation fields in a hash 978 sub updateBlock { 979 my $dbh = shift; 980 my %args = @_; 981 982 return ('FAIL', 'Missing block to update') if !$args{block}; 983 984 # do it all in a transaction 985 local $dbh->{AutoCommit} = 0; 986 local $dbh->{RaiseError} = 1; 987 988 my @fieldlist; 989 my @vallist; 990 foreach ('custid', 'city', 'description', 'notes', 'circuitid', 'privdata') { 991 if ($args{$_}) { 992 push @fieldlist, $_; 993 push @vallist, $args{$_}; 994 } 995 } 996 997 my $updtable = 'allocations'; 998 my $keyfield = 'cidr'; 999 if ($args{type} =~ /^(.)i$/) { 1000 $updtable = 'poolips'; 1001 $keyfield = 'ip'; 1002 } else { 1003 ## fixme: there's got to be a better way... 1004 if ($args{swip}) { 1005 if ($args{swip} eq 'on' || $args{swip} eq '1' || $args{swip} eq 'y') { 1006 $args{swip} = 'y'; 1007 } else { 1008 $args{swip} = 'n'; 1009 } 1010 } 1011 foreach ('type', 'swip') { 1012 if ($args{$_}) { 1013 push @fieldlist, $_; 1014 push @vallist, $args{$_}; 1015 } 1016 } 1017 } 1018 1019 return ('FAIL', 'No fields to update') if !@fieldlist; 1020 1021 push @vallist, $args{block}; 1022 my $sql = "UPDATE $updtable SET "; 1023 $sql .= join " = ?, ", @fieldlist; 1024 $sql .= " = ? WHERE $keyfield = ?"; 1025 1026 eval { 1027 # do the update 1028 $dbh->do($sql, undef, @vallist); 1029 1030 if ($args{node}) { 1031 # done with delete/insert so we don't have to worry about funkyness updating a node ref that isn't there 1032 $dbh->do("DELETE FROM noderef WHERE block = ?", undef, ($args{block}) ); 1033 $dbh->do("INSERT INTO noderef (block,node_id) VALUES (?,?)", undef, ($args{block}, $args{node}) ); 1034 } 1035 1036 $dbh->commit; 1037 }; 1038 if ($@) { 1039 my $msg = $@; 1040 $dbh->rollback; 1041 return ('FAIL', $msg); 1042 } 1043 return 0; 1044 } # end updateBlock() 1045 1046 636 1047 ## IPDB::deleteBlock() 637 1048 # Removes an allocation from the database, including deleting IPs … … 843 1254 844 1255 ## IPDB::getBlockData() 845 # Return custid, type, city, and description for a block 1256 # Get CIDR or IP, custid, type, city, circuit ID, description, notes, modification time, private/restricted 1257 # data, for a CIDR block or pool IP 1258 # Also returns SWIP status flag for CIDR blocks 1259 # Takes the block/IP to look up 1260 # Returns an arrayref to a list of hashrefs 846 1261 sub getBlockData { 847 1262 my $dbh = shift; 848 1263 my $block = shift; 849 1264 850 my $sth = $dbh->prepare("select cidr,custid,type,city,description from searchme". 851 " where cidr='$block'"); 852 $sth->execute(); 853 return $sth->fetchrow_array(); 1265 my $cidr = new NetAddr::IP $block; 1266 1267 my $keycol = 'cidr'; 1268 my $blocktable = 'allocations'; 1269 my $poolip = 0; 1270 1271 # Pool IP and IPv6 check all in one! Still needs to be tightened 1272 # up a little for the as-yet-unhandled case of IPv6 IP pools 1273 if ($cidr->bits == 32 && $cidr->masklen == 32) { 1274 $poolip = 1; 1275 $keycol = 'ip'; 1276 $blocktable = 'poolips'; 1277 } 1278 my $binfo = $dbh->selectrow_hashref("SELECT $keycol AS block, custid, type, city, circuitid, description,". 1279 " notes, modifystamp AS lastmod, privdata".($poolip ? '' : ', swip')." FROM $blocktable". 1280 " WHERE $keycol = ?", undef, ($block) ); 1281 return $binfo; 854 1282 } # end getBlockData() 1283 1284 1285 ## IPDB::getNodeList() 1286 # Gets a list of node ID+name pairs as an arrayref to a list of hashrefs 1287 sub getNodeList { 1288 my $dbh = shift; 1289 1290 my $ret = $dbh->selectall_arrayref("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id", 1291 { Slice => {} }); 1292 return $ret; 1293 } # end getNodeList() 1294 1295 1296 ## IPDB::getNodeName() 1297 # Get node name from the ID 1298 sub getNodeName { 1299 my $dbh = shift; 1300 my $nid = shift; 1301 1302 my ($nname) = $dbh->selectrow_array("SELECT node_name FROM nodes WHERE node_id = ?", undef, ($nid) ); 1303 return $nname; 1304 } # end getNodeName() 1305 1306 1307 ## IPDB::getNodeInfo() 1308 # Get node name and ID associated with a block 1309 sub getNodeInfo { 1310 my $dbh = shift; 1311 my $block = shift; 1312 1313 my ($nid, $nname) = $dbh->selectrow_array("SELECT nodes.node_id,node_name FROM nodes INNER JOIN noderef". 1314 " ON nodes.node_id=noderef.node_id WHERE noderef.block = ?", undef, ($block) ); 1315 return ($nid, $nname); 1316 } # end getNodeInfo() 855 1317 856 1318 -
branches/stable/cgi-bin/admin.cgi
r593 r594 69 69 } 70 70 71 if(!defined($webvar{action})) { 72 $webvar{action} = "main"; #shuts up the warnings. 73 } 74 71 75 # handle DB error output 72 76 if ($webvar{action} eq 'dberr') { … … 88 92 my $header = HTML::Template->new(filename => "admin/header.tmpl"); 89 93 90 if(!defined($webvar{action})) {91 $webvar{action} = "main"; #shuts up the warnings.92 }93 94 94 my $page; 95 95 if (-e "$ENV{HTML_TEMPLATE_ROOT}/admin/$webvar{action}.tmpl") { … … 103 103 $header->param(mainpage => 1); 104 104 105 $sth = $ip_dbh->prepare("select type,listname from alloctypes where listorder < 900 order by listorder"); 106 $sth->execute; 107 108 my @typelist; 109 my $count = 0; 110 while (my ($type,$listname) = $sth->fetchrow_array) { 111 my %row = ( 112 selected => $count++, 113 type => $type, 114 dispname => $listname 115 ); 116 push @typelist, \%row; 117 } 118 $page->param(typelist => \@typelist); 119 120 my @masterlist; 121 $sth = $ip_dbh->prepare("select cidr,mtime from masterblocks order by cidr"); 122 $sth->execute; 123 while (my ($cidr,$mtime) = $sth->fetchrow_array) { 124 my %row = ( 125 master => $cidr, 126 masterdate => $mtime 127 ); 128 push @masterlist, \%row; 129 } 130 $page->param(masterlist => \@masterlist); 131 105 my $tlist = getTypeList($ip_dbh, 'a'); 106 $tlist->[0]->{sel} = 1; 107 $page->param(typelist => $tlist); 108 109 my $mlist = getMasterList($ip_dbh, 'm'); 110 $page->param(masterlist => $mlist); 132 111 } 133 112 … … 136 115 elsif ($webvar{action} eq 'alloc') { 137 116 138 if ($webvar{cidr} !~ /^\s*(\d{1,3}\.){3}\d{1,3}(\/\d{2})?\s*$/) { 117 my $cidr = new NetAddr::IP $webvar{cidr}; 118 if (!$cidr || "$cidr" =~ /^0/) { 139 119 $page->param(errmsg => "Can't allocate something that's not a netblock/ip"); 140 120 goto ERRJUMP; 141 121 } 142 122 143 $sth = $ip_dbh->prepare("select def_custid from alloctypes where type='$webvar{alloctype}'"); 144 $sth->execute; 145 my @data = $sth->fetchrow_array; 146 my $custid = $data[0]; 123 my $custid = $def_custids{$webvar{alloctype}}; 147 124 if ($custid eq '') { 148 if ($webvar{custid} !~ /^(?:\d{10}|\d{7}|STAFF)(?:-\d\d?)?$/) { 149 # Force uppercase for now... 150 $webvar{custid} =~ tr/a-z/A-Z/; 151 # Crosscheck with billing. 152 my $status = CustIDCK->custid_exist($webvar{custid}); 153 if ($CustIDCK::Error) { 154 $page->param(errmsg => "Error verifying customer ID: ".$CustIDCK::ErrMsg); 155 goto ERRJUMP; 156 } 157 if (!$status) { 158 $page->param(errmsg => "Customer ID not valid. Make sure the Customer ID ". 159 "is correct.<br>\nUse STAFF for staff static IPs, and $IPDB::defcustid for any other ". 160 "non-customer assignments."); 161 goto ERRJUMP; 162 } 125 # Crosscheck with billing. 126 my $status = CustIDCK->custid_exist($webvar{custid}); 127 if ($CustIDCK::Error) { 128 $page->param(errmsg => "Error verifying customer ID: ".$CustIDCK::ErrMsg); 129 goto ERRJUMP; 130 } 131 if (!$status) { 132 $page->param(errmsg => "Customer ID not valid. Make sure the Customer ID ". 133 "is correct.<br>\nUse STAFF for staff static IPs, and $IPDB::defcustid for any other ". 134 "non-customer assignments."); 135 goto ERRJUMP; 163 136 } 164 137 # Type that doesn't have a default custid … … 166 139 } 167 140 168 my $cidr = new NetAddr::IP $webvar{cidr}; 169 my @data; 141 my $maskbits = $cidr->masklen; 142 my $fbtmp = findAllocateFrom($ip_dbh, $maskbits, $webvar{alloctype}, '','', 143 (gimme => "$cidr", allowpriv => 1)); 144 170 145 if ($webvar{alloctype} eq 'rm') { 171 $sth = $ip_dbh->prepare("select cidr from freeblocks where cidr >>='$cidr' and routed='n'"); 172 $sth->execute; 173 @data = $sth->fetchrow_array; 174 # User deserves errors if user can't be bothered to find the free block first. 175 if (!$data[0]) { 146 if (!$fbtmp) { 176 147 $page->param(errmsg => "Can't allocate from outside a free block!!"); 177 148 goto ERRJUMP; 178 149 } 179 150 } elsif ($webvar{alloctype} =~ /^(.)i$/) { 180 $sth = $ip_dbh->prepare("select cidr from allocations where cidr >>='$cidr' and (type like '_d' or type like '_p')"); 181 $sth->execute; 182 @data = $sth->fetchrow_array; 183 # User deserves errors if user can't be bothered to find the pool and a free IP first. 184 if (!$data[0]) { 151 my $iptype = $1; 152 my $ptmp = ipParent($ip_dbh, "$cidr"); 153 if ($ptmp->{type} =~ /^(.)[dp]$/) { 154 my $newiptype = "$1i"; 155 $fbtmp = $ptmp->{cidr}; 156 if ($ptmp->{type} !~ /^$iptype./) { 157 $page->param(warnmsg => "Warning: Allocating IP as '".$disp_alloctypes{$newiptype}."' instead of '". 158 $disp_alloctypes{$webvar{alloctype}}."' to match pool $fbtmp\n"); 159 $webvar{alloctype} = $newiptype; 160 } 161 } 162 if (!$fbtmp) { 185 163 $page->param(errmsg => "Can't allocate static IP from outside a pool!!"); 186 164 goto ERRJUMP; 187 165 } 188 166 } else { 189 $sth = $ip_dbh->prepare("select cidr from freeblocks where cidr >>='$cidr' and not (routed='n')"); 190 $sth->execute; 191 @data = $sth->fetchrow_array; 192 # User deserves errors if user can't be bothered to find the free block first. 193 if (!$data[0]) { 167 if (!$fbtmp) { 194 168 $page->param(errmsg => "Can't allocate from outside a routed block!!"); 195 169 goto ERRJUMP; … … 197 171 } 198 172 199 my $alloc_from = new NetAddr::IP $data[0]; 200 $sth->finish; 173 my $alloc_from = new NetAddr::IP $fbtmp; 201 174 202 175 my @cities; … … 226 199 $page->param(locerr => "Invalid customer location! Go back and select customer's location."); 227 200 goto ERRJUMP; 228 } else { 229 if ($webvar{alloctype} =~ /^.i$/) { 230 $sth = $ip_dbh->prepare("update poolips set available='n', custid='$webvar{custid}', ". 231 "city='$webvar{city}', description='$webvar{desc}', notes='$webvar{notes}' ". 232 "where ip='$webvar{cidr}'"); 233 $sth->execute; 234 if ($sth->err) { 235 $page->param(errmsg => $sth->errstr); 236 syslog "err", "($authuser) Allocation of '$webvar{cidr}' to '$webvar{custid}' as ". 237 "'$webvar{alloctype}' failed: '".$sth->errstr."'"; 238 } else { 239 syslog "notice", "$authuser allocated '$webvar{cidr}' to '$webvar{custid}' as ". 240 "'$webvar{alloctype}'"; 241 mailNotify($ip_dbh, "a$webvar{alloctype}", "ADDED: $disp_alloctypes{$webvar{alloctype}} allocation", 242 "$disp_alloctypes{$webvar{alloctype}} $webvar{cidr} allocated to customer $webvar{custid}\n". 243 "Description: $webvar{desc}\n\nAllocated by: $authuser\n"); 244 } 245 } else { 246 my ($retcode,$msg) = allocateBlock($ip_dbh, $webvar{cidr}, $webvar{alloc_from}, 201 } 202 203 my ($retcode,$msg) = allocateBlock($ip_dbh, $webvar{cidr}, $webvar{alloc_from}, 247 204 $webvar{custid}, $webvar{alloctype}, $webvar{city}, $webvar{desc}, $webvar{notes}, 248 205 $webvar{circid}); 249 if ($retcode eq 'OK') { 250 syslog "notice", "$authuser allocated '$webvar{cidr}' to '$webvar{custid}' as ". 251 "'$webvar{alloctype}'"; 252 } else { 253 $page->param(errmsg => $msg); 254 syslog "err", "($authuser) Allocation of '$webvar{cidr}' to '$webvar{custid}' as ". 255 "'$webvar{alloctype}' failed: '$msg'"; 256 } 257 } # static IP vs netblock 258 259 } # done city check 206 if ($retcode eq 'OK') { 207 syslog "notice", "$authuser allocated '$webvar{cidr}' to '$webvar{custid}' as ". 208 "'$webvar{alloctype}'"; 209 if ($webvar{alloctype} =~ /^.i$/) { 210 mailNotify($ip_dbh, "a$webvar{alloctype}", "ADDED: $disp_alloctypes{$webvar{alloctype}} allocation", 211 "$disp_alloctypes{$webvar{alloctype}} $webvar{cidr} allocated to customer $webvar{custid}\n". 212 "Description: $webvar{desc}\n\nAllocated by: $authuser\n"); 213 } 214 } else { 215 $page->param(errmsg => $msg); 216 syslog "err", "($authuser) Allocation of '$webvar{cidr}' to '$webvar{custid}' as ". 217 "'$webvar{alloctype}' failed: '$msg'"; 218 } 260 219 261 220 } elsif ($webvar{action} eq 'alloctweak') { … … 270 229 } elsif ($webvar{action} eq 'touch') { 271 230 272 $page->param(master => $webvar{whichmaster}); 273 $sth = $ip_dbh->prepare("update masterblocks set mtime=now() where cidr='$webvar{whichmaster}'"); 274 $sth->execute; 275 if ($sth->err) { 276 $page->param(errmsg => $sth->errstr); 277 } 231 my ($code,$msg) = touchMaster($ip_dbh, $webvar{whichmaster}); 232 $page->param(errmsg => $msg) if $code eq 'FAIL'; 278 233 279 234 } elsif ($webvar{action} eq 'listcust') { … … 612 567 # List all IPs in a pool, and allow arbitrary admin changes to each 613 568 # Allow changes to ALL fields 614 sub showPool ($){569 sub showPool { 615 570 my $pool = new NetAddr::IP $_[0]; 616 571 … … 627 582 $page->param(typelist => \@typelist); 628 583 629 $sth = $ip_dbh->prepare("select ip,custid,city,type,available,description,notes from poolips where pool='$pool' order by ip"); 630 $sth->execute; 584 $sth = $ip_dbh->prepare("SELECT ip,custid,city,type,available,description,notes from poolips". 585 " WHERE pool=? ORDER BY ip"); 586 $sth->execute($pool); 631 587 my @iplist; 632 588 while (my ($ip,$custid,$city,$type,$avail,$desc,$notes) = $sth->fetchrow_array) { -
branches/stable/cgi-bin/main.cgi
r593 r594 60 60 # Use the connectDB function, otherwise we end up confusing ourselves 61 61 my $ip_dbh; 62 my $sth;63 62 my $errstr; 64 63 ($ip_dbh,$errstr) = connectDB_My; … … 90 89 my $page; 91 90 if (-e "$ENV{HTML_TEMPLATE_ROOT}/$webvar{action}.tmpl") { 92 $page = HTML::Template->new(filename => "$webvar{action}.tmpl" );91 $page = HTML::Template->new(filename => "$webvar{action}.tmpl", loop_context_vars => 1, global_vars => 1); 93 92 } else { 94 93 $page = HTML::Template->new(filename => "dunno.tmpl"); … … 129 128 } 130 129 elsif($webvar{action} eq 'listpool') { 131 listPool();130 showPool(); 132 131 } 133 132 … … 155 154 } 156 155 elsif ($webvar{action} eq 'nodesearch') { 157 $sth = $ip_dbh->prepare("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id"); 158 $sth->execute() or $page->param(errmsg => $sth->errstr); 159 my @nodelist; 160 while (my ($nid,$nname) = $sth->fetchrow_array()) { 161 my %row = (nodeid => $nid, nodename => $nname); 162 push @nodelist, \%row; 163 } 164 $page->param(nodelist => \@nodelist); 156 my $nodelist = getNodeList($ip_dbh); 157 $page->param(nodelist => $nodelist); 165 158 } 166 159 … … 201 194 } 202 195 203 204 196 # Clean up IPDB globals, DB handle, etc. 205 197 finish($ip_dbh); … … 224 216 # Initial display: Show master blocks with total allocated subnets, total free subnets 225 217 sub showSummary { 226 my %allocated; 227 my %free; 228 my %routed; 229 my %bigfree; 230 231 # Count the allocations. 232 $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?"); 233 foreach my $master (@masterblocks) { 234 $sth->execute("$master"); 235 $sth->bind_columns(\$allocated{"$master"}); 236 $sth->fetch(); 237 } 238 239 # Count routed blocks 240 $sth = $ip_dbh->prepare("select count(*) from routed where cidr <<= ?"); 241 foreach my $master (@masterblocks) { 242 $sth->execute("$master"); 243 $sth->bind_columns(\$routed{"$master"}); 244 $sth->fetch(); 245 } 246 247 # Count the free blocks. 248 $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ? and ". 249 "(routed='y' or routed='n')"); 250 foreach my $master (@masterblocks) { 251 $sth->execute("$master"); 252 $sth->bind_columns(\$free{"$master"}); 253 $sth->fetch(); 254 } 255 256 # Find the largest free block in each master 257 $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? and ". 258 "(routed='y' or routed='n') order by maskbits limit 1"); 259 foreach my $master (@masterblocks) { 260 $sth->execute("$master"); 261 $sth->bind_columns(\$bigfree{"$master"}); 262 $sth->fetch(); 263 } 264 265 # Assemble the data to stuff into the template. 266 my @masterlist; 267 my $rowclass=0; 268 foreach my $master (@masterblocks) { 269 my %row = ( 270 rowclass => $rowclass++ % 2, 271 master => "$master", 272 routed => $routed{"$master"}, 273 allocated => $allocated{"$master"}, 274 free => $free{"$master"}, 275 bigfree => ( ($bigfree{"$master"} eq '') ? ("<NONE>") : ("/".$bigfree{"$master"}) ) 276 ); 277 push (@masterlist, \%row); 278 } 279 $page->param(masterlist => \@masterlist); 218 my $masterlist = listSummary($ip_dbh); 219 $page->param(masterlist => $masterlist); 280 220 281 221 $page->param(addmaster => ($IPDBacl{$authuser} =~ /a/) ); 282 283 222 } # showSummary 284 223 … … 292 231 293 232 $page->param(master => $webvar{block}); 294 295 my %allocated;296 my %free;297 my %cities;298 my %bigfree;299 300 my $master = new NetAddr::IP $webvar{block};301 my @localmasters;302 303 # Fetch only the blocks relevant to this master304 $sth = $ip_dbh->prepare("select cidr,city from routed where cidr <<= '$master' order by cidr");305 $sth->execute();306 307 my $i=0;308 while (my @data = $sth->fetchrow_array()) {309 my $cidr = new NetAddr::IP $data[0];310 $localmasters[$i++] = $cidr;311 $free{"$cidr"} = 0;312 $allocated{"$cidr"} = 0;313 $bigfree{"$cidr"} = 128;314 # Retain the routing destination315 $cities{"$cidr"} = $data[1];316 }317 318 # Check if there were actually any blocks routed from this master319 if ($i > 0) {320 321 # Count the allocations322 $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?");323 foreach my $master (@localmasters) {324 $sth->execute("$master");325 $sth->bind_columns(\$allocated{"$master"});326 $sth->fetch();327 }328 329 # Count the free blocks.330 $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ? and ".331 "(routed='y' or routed='n')");332 foreach my $master (@localmasters) {333 $sth->execute("$master");334 $sth->bind_columns(\$free{"$master"});335 $sth->fetch();336 }337 338 # Get the size of the largest free block339 $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? and ".340 "(routed='y' or routed='n') order by maskbits limit 1");341 foreach my $master (@localmasters) {342 $sth->execute("$master");343 $sth->bind_columns(\$bigfree{"$master"});344 $sth->fetch();345 }346 347 my @routed;348 my $rowclass = 0;349 foreach my $master (@localmasters) {350 my %row = (351 rowclass => $rowclass++ % 2,352 block => "$master",353 city => $cities{"$master"},354 nsubs => $allocated{"$master"},355 nfree => $free{"$master"},356 lfree => ( ($bigfree{"$master"} eq 128) ? ("<NONE>") : ("/".$bigfree{"$master"}) )357 );358 push @routed, \%row;359 }360 $page->param(routedlist => \@routed);361 362 } # end check for existence of routed blocks in master363 364 233 $page->param(delmaster => ($IPDBacl{$authuser} =~ /d/)); 365 234 366 # Snag the free blocks. 367 my $count = 0; 368 $sth = $ip_dbh->prepare("select cidr from freeblocks where cidr <<='$master' and ". 369 "routed='n' order by cidr"); 370 $sth->execute(); 371 my @unrouted; 372 my $rowclass = 0; 373 while (my @data = $sth->fetchrow_array()) { 374 my $cidr = new NetAddr::IP $data[0]; 375 my %row = ( 376 rowclass => $rowclass++ % 2, 377 fblock => "$cidr", 378 frange => $cidr->range 379 ); 380 push @unrouted, \%row; 381 } 382 $page->param(unrouted => \@unrouted); 383 235 my $rlist = listMaster($ip_dbh, $webvar{block}); 236 $page->param(routedlist => $rlist); 237 238 my $flist = listFree($ip_dbh, $webvar{block}); 239 $page->param(unrouted => $flist); 384 240 } # showMaster 385 241 … … 394 250 sub showRBlock { 395 251 396 my $master = new NetAddr::IP $webvar{block}; 397 398 $sth = $ip_dbh->prepare("select city from routed where cidr='$master'"); 399 $sth->execute; 400 my ($rcity) = $sth->fetchrow_array; 401 402 $page->param(master => "$master"); 252 $page->param(master => $webvar{block}); 253 $page->param(delrouted => $IPDBacl{$authuser} =~ /d/); 254 255 my $rcity = getRoutedCity($ip_dbh, $webvar{block}); 403 256 $page->param(rcity => $rcity); 404 257 405 # Snag the allocations for this block 406 $sth = $ip_dbh->prepare("select cidr,city,type,custid,swip,description". 407 " from allocations where cidr <<= '$master' order by cidr"); 408 $sth->execute(); 409 410 # hack hack hack 411 # set up to flag swip=y records if they don't actually have supporting data in the customers table 412 my $custsth = $ip_dbh->prepare("select count(*) from customers where custid=?"); 413 414 my $rowclass = 0; 415 my @blocklist; 416 while (my ($cidr,$city,$type,$custid,$swip,$desc) = $sth->fetchrow_array()) { 417 $custsth->execute($custid); 418 my ($ncust) = $custsth->fetchrow_array(); 419 420 my %row = ( 421 rowclass => $rowclass++ % 2, 422 block => $cidr, 423 city => $city, 424 type => $disp_alloctypes{$type}, 425 custid => $custid, 426 swip => ($swip eq 'y' ? ($ncust == 0 ? 'Yes<small>*</small>' : 'Yes') : 'No'), 427 desc => $desc 428 ); 429 $row{subblock} = ($type =~ /^.r$/); # hmf. wonder why these won't work in the hash declaration... 430 $row{listpool} = ($type =~ /^.[pd]$/); 431 push (@blocklist, \%row); 432 } 433 $page->param(blocklist => \@blocklist); 434 435 $page->param(delrouted => $IPDBacl{$authuser} =~ /d/); 436 437 # Snag the free blocks. We don't really *need* to be pedantic about avoiding 438 # unrouted free blocks, but it's better to let the database do the work if we can. 439 $rowclass = 0; 440 my @unassigned; 441 $sth = $ip_dbh->prepare("select cidr,routed from freeblocks where cidr <<= '$master'". 442 " order by cidr"); 443 $sth->execute(); 444 while (my ($cidr_db,$routed) = $sth->fetchrow_array()) { 445 my $cidr = new NetAddr::IP $cidr_db; 446 447 my %row = ( 448 rowclass => $rowclass++ % 2, 449 subblock => ($routed ne 'y' && $routed ne 'n'), 450 fblock => $cidr_db, 451 fbtype => $routed, 452 frange => $cidr->range, 453 ); 454 push @unassigned, \%row; 455 } 456 $page->param(unassigned => \@unassigned); 457 258 my $blist = listRBlock($ip_dbh, $webvar{block}); 259 $page->param(blocklist => $blist); 260 261 my $flist = listFree($ip_dbh, $webvar{block}, 'y'); 262 $page->param(unassigned => $flist); 458 263 } # showRBlock 459 264 460 265 461 266 # List the IPs used in a pool 462 sub listPool {267 sub showPool { 463 268 464 269 my $cidr = new NetAddr::IP $webvar{pool}; … … 473 278 474 279 # Snag pool info for heading 475 $sth = $ip_dbh->prepare("select type,city from allocations where cidr=?"); 476 $sth->execute($webvar{pool}); 477 my ($pooltype, $poolcity) = $sth->fetchrow_array; 478 479 $page->param(disptype => $disp_alloctypes{$pooltype}); 480 $page->param(city => $poolcity); 280 my $poolinfo = getBlockData($ip_dbh, $webvar{pool}); 281 282 $page->param(disptype => $disp_alloctypes{$poolinfo->{type}}); 283 $page->param(city => $poolinfo->{city}); 481 284 482 285 # Only display net/gw/bcast if it's a "real" netblock and not a PPP(oE) lunacy 483 $page->param(realblock => $pool type=~ /^.d$/);286 $page->param(realblock => $poolinfo->{type} =~ /^.d$/); 484 287 485 288 # probably have to add an "edit IP allocation" link here somewhere. 486 289 487 $sth = $ip_dbh->prepare("select ip,custid,available,description,type". 488 " from poolips where pool='$webvar{pool}' order by ip"); 489 $sth->execute; 490 my @poolips; 491 my $rowclass = 0; 492 while (my ($ip,$custid,$available,$desc,$type) = $sth->fetchrow_array) { 493 my %row = ( 494 rowclass => $rowclass++ % 2, 495 ip => $ip, 496 custid => $custid, 497 available => $available, 498 desc => $desc, 499 maydel => $IPDBacl{$authuser} =~ /d/, 500 delme => $available eq 'n' 501 ); 502 push @poolips, \%row; 503 } 504 $page->param(poolips => \@poolips); 505 506 } # end listPool 290 my $plist = listPool($ip_dbh, $webvar{pool}); 291 # technically slightly more efficient to check the ACL in an if () once outside the foreach 292 foreach (@{$plist}) { 293 $$_{maydel} = $IPDBacl{$authuser} =~ /d/; 294 } 295 $page->param(poolips => $plist); 296 } # end showPool 507 297 508 298 … … 535 325 if ($webvar{fbtype} ne 'y') { 536 326 # Snag the type of the container block from the database. 537 $sth = $ip_dbh->prepare("select type from allocations where cidr >>='$block'"); 538 $sth->execute;539 my @data = $sth->fetchrow_array;540 $ data[0] =~ s/c$/r/; # Munge the type into the correct form541 $page->param(fbdisptype => $list_alloctypes{$ data[0]});542 $page->param(type => $ data[0]);327 ## hmm. need a flag for parent class/type, sort of? 328 my $pblock = subParent($ip_dbh, $webvar{block}); 329 my $ptype = $pblock->{type}; 330 $ptype =~ s/c$/r/; 331 $page->param(fbdisptype => $list_alloctypes{$ptype}); 332 $page->param(type => $ptype); 543 333 } else { 544 $sth = $ip_dbh->prepare("select type,listname from alloctypes where listorder < 500 ". 545 "and type not like '_i' order by listorder"); 546 $sth->execute; 547 my @typelist; 548 my $selflag = 0; 549 while (my @data = $sth->fetchrow_array) { 550 my %row = (tval => $data[0], 551 type => $data[1], 552 sel => ($selflag == 0 ? ' selected' : '') 553 ); 554 push (@typelist, \%row); 555 $selflag++; 556 } 557 $page->param(typelist => \@typelist); 334 # get "primary" alloctypes, since these are all that can correctly be assigned if we're in this branch 335 my $tlist = getTypeList($ip_dbh, 'p'); 336 $tlist->[0]->{sel} = 1; 337 $page->param(typelist => $tlist); 558 338 } 559 339 } else { 560 my @masterlist; 561 foreach my $master (@masterblocks) { 562 my %row = (master => "$master"); 563 push (@masterlist, \%row); 564 } 565 $page->param(masterlist => \@masterlist); 340 my $mlist = getMasterList($ip_dbh, 'c'); 341 $page->param(masterlist => $mlist); 566 342 567 343 my @pops; … … 572 348 $page->param(pops => \@pops); 573 349 574 # could arguably include routing (500) in the list, but ATM it doesn't 575 # make sense, and in any case that shouldn't be structurally possible here. 576 $sth = $ip_dbh->prepare("select type,listname from alloctypes where listorder <= 500 order by listorder"); 577 $sth->execute; 578 my @typelist; 579 my $selflag = 0; 580 while (my @data = $sth->fetchrow_array) { 581 my %row = (tval => $data[0], 582 type => $data[1], 583 sel => ($selflag == 0 ? ' selected' : '') 584 ); 585 push (@typelist, \%row); 586 $selflag++; 587 } 588 $page->param(typelist => \@typelist); 350 # get all standard alloctypes 351 my $tlist = getTypeList($ip_dbh, 'a'); 352 $tlist->[0]->{sel} = 1; 353 $page->param(typelist => $tlist); 589 354 } 590 355 … … 597 362 598 363 ## node hack 599 $sth = $ip_dbh->prepare("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id"); 600 $sth->execute() or print "DEBUG: failed retrieval from nodes: ".$sth->errstr,"<br>\n"; 601 my @nodes; 602 while (my ($nid,$nname) = $sth->fetchrow_array()) { 603 my %row = (nid => $nid, nname => $nname); 604 push (@nodes, \%row); 605 } 606 $page->param(nodelist => \@nodes); 364 my $nlist = getNodeList($ip_dbh); 365 $page->param(nodelist => $nlist); 607 366 ## end node hack 608 367 … … 632 391 633 392 if ($webvar{alloctype} =~ /^.i$/ && $webvar{fbassign} ne 'y') { 634 my ($base,undef) = split //, $webvar{alloctype}; # split into individual chars 635 636 # Ewww. But it works. 637 $sth = $ip_dbh->prepare("SELECT (SELECT city FROM allocations WHERE cidr=poolips.pool), ". 638 "poolips.pool, COUNT(*) FROM poolips,allocations WHERE poolips.available='y' AND ". 639 "poolips.pool=allocations.cidr AND allocations.city='$webvar{pop}' AND poolips.type LIKE '".$base."_' ". 640 "GROUP BY pool"); 641 $sth->execute; 642 my $optionlist; 643 644 my @poollist; 645 while (my ($poolcit,$poolblock,$poolfree) = $sth->fetchrow_array) { 646 # city,pool cidr,free IP count 647 if ($poolfree > 0) { 648 my %row = (poolcit => $poolcit, poolblock => $poolblock, poolfree => $poolfree); 649 push (@poollist, \%row); 650 } 651 } 393 my $plist = getPoolSelect($ip_dbh, $webvar{alloctype}, $webvar{pop}); 652 394 $page->param(staticip => 1); 653 $page->param(poollist => \@poollist);395 $page->param(poollist => $plist) if $plist; 654 396 $cidr = "Single static IP"; 655 397 ##fixme: need to handle "no available pools" … … 657 399 } else { # end show pool options 658 400 659 if ($webvar{fbassign} eq 'y') {401 if ($webvar{fbassign} && $webvar{fbassign} eq 'y') { 660 402 $alloc_from = new NetAddr::IP $webvar{allocfrom}; 661 403 ## possibly messy behaviour: force the _from and block to be the network addr? … … 669 411 return; 670 412 } 671 my $sql; 672 my $city; 673 my $failmsg; 674 my $extracond = ''; 675 if ($webvar{allocfrom} eq '-') { 676 $extracond = ($webvar{allowpriv} eq 'on' ? '' : 677 " and not (cidr <<= '192.168.0.0/16'". 678 " or cidr <<= '10.0.0.0/8'". 679 " or cidr <<= '172.16.0.0/12')"); 680 } 681 my $sortorder; 413 414 ##fixme ick, ew, bleh. gotta handle the failure message generation better. push it into findAllocateFrom()? 415 my $failmsg = "No suitable free block found.<br>\n"; 682 416 if ($webvar{alloctype} eq 'rm') { 683 if ($webvar{allocfrom} ne '-') { 684 $sql = "select * from freeblocks where maskbits<=$webvar{maskbits} and routed='n'". 685 " and cidr <<= '$webvar{allocfrom}'"; 686 $sortorder = "maskbits desc"; 687 } else { 688 $sql = "select * from freeblocks where maskbits<=$webvar{maskbits} and routed='n'"; 689 $sortorder = "maskbits desc"; 690 } 691 $failmsg = "No suitable free block found.<br>\nWe do not have a free". 692 " routeable block of that size.<br>\nYou will have to either route". 693 " a set of smaller netblocks or a single smaller netblock."; 417 $failmsg .= "We do not have a free routeable block of that size.<br>\n". 418 "You will have to either route a set of smaller netblocks or a single smaller netblock."; 694 419 } else { 695 ##fixme696 # This section needs serious Pondering.697 # Pools of most types get assigned to the POP they're "routed from"698 # This includes WAN blocks and other netblock "containers"699 # This does NOT include cable pools.700 420 if ($webvar{alloctype} =~ /^.[pc]$/) { 701 $city = $webvar{city}; 702 $failmsg = "No suitable free block found.<br>\nYou will have to route another". 703 " superblock from one of the<br>\nmaster blocks or chose a smaller". 704 " block size for the pool."; 421 $failmsg .= "You will have to route another superblock from one of the<br>\n". 422 "master blocks or chose a smaller block size for the pool."; 705 423 } else { 706 424 if (!$webvar{pop}) { … … 708 426 return; 709 427 } 710 $city = $webvar{pop}; 711 $failmsg = "No suitable free block found.<br>\nYou will have to route another". 712 " superblock to $webvar{pop}<br>\nfrom one of the master blocks or". 713 " chose a smaller blocksize."; 714 } 715 if (defined $webvar{allocfrom} && $webvar{allocfrom} ne '-') { 716 $sql = "select cidr from freeblocks where city='$city' and maskbits<=$webvar{maskbits}". 717 " and cidr <<= '$webvar{allocfrom}' and routed='". 718 (($webvar{alloctype} =~ /^(.)r$/) ? "$1" : 'y')."'"; 719 $sortorder = "maskbits desc,cidr"; 720 } else { 721 $sql = "select cidr from freeblocks where city='$city' and maskbits<=$webvar{maskbits}". 722 " and routed='".(($webvar{alloctype} =~ /^(.)r$/) ? "$1" : 'y')."'"; 723 $sortorder = "maskbits desc,cidr"; 428 $failmsg .= "You will have to route another superblock to $webvar{pop}<br>\n". 429 "from one of the master blocks or chose a smaller blocksize."; 724 430 } 725 431 } 726 $sql = $sql.$extracond." order by ".$sortorder; 727 $sth = $ip_dbh->prepare($sql); 728 $sth->execute; 729 my @data = $sth->fetchrow_array(); 730 if ($data[0] eq "") { 432 433 $cidr = findAllocateFrom($ip_dbh, $webvar{maskbits}, $webvar{alloctype}, $webvar{city}, $webvar{pop}, 434 (master => $webvar{allocfrom}, allowpriv => $webvar{allowpriv}) ); 435 if (!$cidr) { 731 436 $page->param(err => $failmsg); 732 437 return; 733 438 } 734 $cidr = new NetAddr::IP $ data[0];439 $cidr = new NetAddr::IP $cidr; 735 440 736 441 # this chunk now specific to "guided" allocation; freeblock-select can now slice-n-dice on its own. … … 754 459 ## node hack 755 460 if ($webvar{node} && $webvar{node} ne '-') { 756 $sth = $ip_dbh->prepare("SELECT node_name FROM nodes WHERE node_id=?"); 757 $sth->execute($webvar{node}); 758 my ($nodename) = $sth->fetchrow_array(); 461 my $nodename = getNodeName($ip_dbh, $webvar{node}); 759 462 $page->param(nodename => $nodename); 760 463 $page->param(nodeid => $webvar{node}); … … 875 578 return; 876 579 } 877 if ($webvar{custid} !~ /^(?:\d{10}|\d{7}|STAFF)(?:-\d\d?)?$/) { 878 # Force uppercase for now... 879 $webvar{custid} =~ tr/a-z/A-Z/; 880 # Crosscheck with billing. 881 my $status = CustIDCK->custid_exist($webvar{custid}); 882 if ($CustIDCK::Error) { 883 $page->param(err => "Error verifying customer ID: ".$CustIDCK::ErrMsg); 884 return; 885 } 886 if (!$status) { 887 $page->param(err => "Customer ID not valid. Make sure the Customer ID ". 888 "is correct.<br>\nUse STAFF for staff static IPs, and $IPDB::defcustid for any other ". 889 "non-customer assignments."); 890 return; 891 } 580 # Crosscheck with billing. 581 my $status = CustIDCK->custid_exist($webvar{custid}); 582 if ($CustIDCK::Error) { 583 $page->param(err => "Error verifying customer ID: ".$CustIDCK::ErrMsg); 584 return; 585 } 586 if (!$status) { 587 $page->param(err => "Customer ID not valid. Make sure the Customer ID ". 588 "is correct.<br>\nUse STAFF for staff static IPs, and $IPDB::defcustid for any other ". 589 "non-customer assignments."); 590 return; 892 591 } 893 592 # print "<!-- [ In validateInput(). Insert customer ID cross-check here. ] -->\n"; … … 913 612 ##fixme: hook to force-set POP or city on certain alloctypes 914 613 # if ($webvar{alloctype =~ /foo,bar,bz/ { $webvar{pop} = 'blah'; } 915 if ($webvar{pop} =~ /^-$/) {614 if ($webvar{pop} && $webvar{pop} =~ /^-$/) { 916 615 $flag = 'to route the block from/through'; 917 616 } … … 935 634 sub edit { 936 635 937 my $sql; 938 939 # Two cases: block is a netblock, or block is a static IP from a pool 940 # because I'm lazy, we'll try to make the SELECT's bring out identical)ish) data 941 ##fixme: allow "SWIP" (publication to rWHOIS) of static IP data 942 if ($webvar{block} =~ /\/32$/) { 943 $sql = "select ip,custid,type,city,circuitid,description,notes,modifystamp,privdata from poolips where ip='$webvar{block}'"; 944 } else { 945 $sql = "select cidr,custid,type,city,circuitid,description,notes,modifystamp,privdata,swip from allocations where cidr='$webvar{block}'" 946 } 947 948 # gotta snag block info from db 949 $sth = $ip_dbh->prepare($sql); 950 $sth->execute; 951 my @data = $sth->fetchrow_array; 952 953 # Clean up extra whitespace on alloc type 954 $data[2] =~ s/\s//; 955 956 # We can't let the city be changed here; this block is a part of 957 # a larger routed allocation and therefore by definition can't be moved. 958 # block and city are static. 959 ##fixme 960 # Needs thinking. Have to allow changes to city to correct errors, no? 961 # Also have areas where a routed block at a POP serves "many" cities/towns/named crossroads 962 963 # @data: cidr,custid,type,city,circuitid,description,notes,modifystamp,privdata,swip 636 # snag block info from db 637 my $blockinfo = getBlockData($ip_dbh, $webvar{block}); 638 639 # Clean up extra whitespace on alloc type. Mainly a legacy-data cleanup. 640 $blockinfo->{type} =~ s/\s//; 964 641 965 642 $page->param(block => $webvar{block}); 966 643 967 $page->param(custid => $data[1]);968 $page->param(city => $data[3]);969 $page->param(circid => $data[4]);970 $page->param(desc => $data[5]);971 $page->param(notes => $data[6]);644 $page->param(custid => $blockinfo->{custid}); 645 $page->param(city => $blockinfo->{city}); 646 $page->param(circid => $blockinfo->{circuitid}); 647 $page->param(desc => $blockinfo->{description}); 648 $page->param(notes => $blockinfo->{notes}); 972 649 973 650 ##fixme The check here should be built from the database 974 651 # Need to expand to support pool types too 975 if ($ data[2]=~ /^.[ne]$/ && $IPDBacl{$authuser} =~ /c/) {652 if ($blockinfo->{type} =~ /^.[ne]$/ && $IPDBacl{$authuser} =~ /c/) { 976 653 $page->param(changetype => 1); 977 654 $page->param(alloctype => [ 978 { selme => ($ data[2]eq 'me'), type => "me", disptype => "Dialup netblock" },979 { selme => ($ data[2]eq 'de'), type => "de", disptype => "Dynamic DSL netblock" },980 { selme => ($ data[2]eq 'ce'), type => "ce", disptype => "Dynamic cable netblock" },981 { selme => ($ data[2]eq 'we'), type => "we", disptype => "Dynamic wireless netblock" },982 { selme => ($ data[2]eq 'cn'), type => "cn", disptype => "Customer netblock" },983 { selme => ($ data[2]eq 'en'), type => "en", disptype => "End-use netblock" },984 { selme => ($ data[2]eq 'in'), type => "in", disptype => "Internal netblock" },655 { selme => ($blockinfo->{type} eq 'me'), type => "me", disptype => "Dialup netblock" }, 656 { selme => ($blockinfo->{type} eq 'de'), type => "de", disptype => "Dynamic DSL netblock" }, 657 { selme => ($blockinfo->{type} eq 'ce'), type => "ce", disptype => "Dynamic cable netblock" }, 658 { selme => ($blockinfo->{type} eq 'we'), type => "we", disptype => "Dynamic wireless netblock" }, 659 { selme => ($blockinfo->{type} eq 'cn'), type => "cn", disptype => "Customer netblock" }, 660 { selme => ($blockinfo->{type} eq 'en'), type => "en", disptype => "End-use netblock" }, 661 { selme => ($blockinfo->{type} eq 'in'), type => "in", disptype => "Internal netblock" }, 985 662 ] 986 663 ); 987 664 } else { 988 $page->param(disptype => $disp_alloctypes{$ data[2]});989 $page->param(type => $ data[2]);665 $page->param(disptype => $disp_alloctypes{$blockinfo->{type}}); 666 $page->param(type => $blockinfo->{type}); 990 667 } 991 668 992 669 ## node hack 993 $sth = $ip_dbh->prepare("SELECT nodes.node_id,node_name FROM nodes INNER JOIN noderef". 994 " ON nodes.node_id=noderef.node_id WHERE noderef.block='$webvar{block}'"); 995 $sth->execute; 996 my ($nodeid,$nodename) = $sth->fetchrow_array(); 670 my ($nodeid,$nodename) = getNodeInfo($ip_dbh, $webvar{block}); 997 671 $page->param(havenodeid => $nodeid); 998 672 999 if ($ data[2] eq 'fr' || $data[2]eq 'bi') {673 if ($blockinfo->{type} eq 'fr' || $blockinfo->{type} eq 'bi') { 1000 674 $page->param(typesupportsnodes => 1); 1001 675 $page->param(nodename => $nodename); … … 1006 680 # (currently) have a nodeid set in the first place. 1007 681 if ($IPDBacl{$authuser} =~ /c/) { 1008 $sth = $ip_dbh->prepare("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id"); 1009 $sth->execute; 1010 my @nodelist; 1011 while (my ($nid,$nname) = $sth->fetchrow_array()) { 1012 my %row = ( 1013 selme => ($nodeid == $nid), 1014 nodeid => $nid, 1015 nodename => $nname, 1016 ); 1017 push (@nodelist, \%row); 682 my $nlist = getNodeList($ip_dbh); 683 foreach (@{$nlist}) { 684 $$_{selme} = ($$_{node_id} == $nodeid); 1018 685 } 1019 $page->param(nodelist => \@nodelist);686 $page->param(nodelist => $nlist); 1020 687 } 1021 688 } 1022 689 ## end node hack 1023 690 1024 my ($lastmod,undef) = split /\s+/, $ data[7];691 my ($lastmod,undef) = split /\s+/, $blockinfo->{lastmod}; 1025 692 $page->param(lastmod => $lastmod); 1026 693 1027 694 # not happy with the upside-down logic, but... 1028 $page->param(swipable => $ data[2]!~ /.i/);1029 $page->param(swip => $ data[10] ne 'n');695 $page->param(swipable => $blockinfo->{type} !~ /.i/); 696 $page->param(swip => $blockinfo->{swip} ne 'n') if $blockinfo->{swip}; 1030 697 1031 698 # Check to see if we can display sensitive data 1032 699 $page->param(nocling => $IPDBacl{$authuser} =~ /s/); 1033 $page->param(privdata => $ data[8]);700 $page->param(privdata => $blockinfo->{privdata}); 1034 701 1035 702 # ACL trickery - these two template booleans control the presence of all form/input tags … … 1048 715 } 1049 716 1050 # Check to see if we can update restricted data1051 my $privdata = '';1052 if ($IPDBacl{$authuser} =~ /s/) {1053 $privdata = ",privdata='$webvar{privdata}'";1054 }1055 1056 717 # Make sure incoming data is in correct format - custID among other things. 1057 718 return if !validateInput; 1058 719 1059 # SQL transaction wrapper 1060 eval { 1061 # Relatively simple SQL transaction here. 1062 my $sql; 1063 if (my $pooltype = ($webvar{alloctype} =~ /^(.)i$/) ) { 1064 $sql = "UPDATE poolips SET custid='$webvar{custid}',". 1065 "city=?,description=?,notes=?,". 1066 "circuitid='$webvar{circid}',". 1067 "$privdata where ip='$webvar{block}'"; 1068 } else { 1069 $sql = "UPDATE allocations SET custid='$webvar{custid}',". 1070 "city=?,description=?,notes=?,". 1071 "circuitid='$webvar{circid}'$privdata,". 1072 "type='$webvar{alloctype}',". 1073 "swip='".($webvar{swip} eq 'on' ? 'y' : 'n')."' ". 1074 "where cidr='$webvar{block}'"; 1075 } 1076 # Log the details of the change. 1077 syslog "debug", $sql; 1078 $sth = $ip_dbh->prepare($sql); 1079 $sth->execute($webvar{city}, $webvar{desc}, $webvar{notes}); 1080 ## node hack 1081 if ($webvar{node}) { 1082 # done with delete/insert so we don't have to worry about funkyness updating a node ref that isn't there 1083 $ip_dbh->do("DELETE FROM noderef WHERE block='$webvar{block}'"); 1084 $sth = $ip_dbh->prepare("INSERT INTO noderef (block,node_id) VALUES (?,?)"); 1085 $sth->execute($webvar{block},$webvar{node}); 1086 } 1087 ## end node hack 1088 $ip_dbh->commit; 1089 }; 1090 if ($@) { 1091 my $msg = $@; 1092 eval { $ip_dbh->rollback; }; 720 $webvar{swip} = 'n' if !$webvar{swip}; 721 722 my %updargs = ( 723 custid => $webvar{custid}, 724 city => $webvar{city}, 725 description => $webvar{desc}, 726 notes => $webvar{notes}, 727 circuitid => $webvar{circid}, 728 block => $webvar{block}, 729 type => $webvar{alloctype}, 730 swip => $webvar{swip}, 731 ); 732 733 # Semioptional values 734 $updargs{privdata} = $webvar{privdata} if $IPDBacl{$authuser} =~ /s/; 735 $updargs{node} = $webvar{node} if $webvar{node}; 736 737 my ($code,$msg) = updateBlock($ip_dbh, %updargs); 738 739 if ($code eq 'FAIL') { 1093 740 syslog "err", "$authuser could not update block/IP '$webvar{block}': '$msg'"; 1094 741 $page->param(err => "Could not update block/IP $webvar{block}: $msg"); … … 1098 745 # If we get here, the operation succeeded. 1099 746 syslog "notice", "$authuser updated $webvar{block}"; 747 ##fixme: log details of the change? old way is in the .debug stream anyway. 1100 748 ##fixme: need to wedge something in to allow "update:field" notifications 1101 749 ## hmm. how to tell what changed? O_o … … 1105 753 ## node hack 1106 754 if ($webvar{node} && $webvar{node} ne '-') { 1107 $sth = $ip_dbh->prepare("SELECT node_name FROM nodes WHERE node_id=?"); 1108 $sth->execute($webvar{node}); 1109 my ($nodename) = $sth->fetchrow_array(); 755 my $nodename = getNodeName($ip_dbh, $webvar{node}); 1110 756 $page->param(nodename => $nodename); 1111 757 } … … 1113 759 1114 760 # Link back to browse-routed or list-pool page on "Update complete" page. 1115 my $cblock; # to contain the CIDR of the container block we're retrieving. 1116 my $sql; 761 my $cblock; 1117 762 if (my $pooltype = ($webvar{alloctype} =~ /^(.)i$/) ) { 1118 763 $page->param(backpool => 1); 1119 $ sql = "select pool from poolips where ip='$webvar{block}'";764 $cblock = ipParent($ip_dbh, $webvar{block}); 1120 765 } else { 1121 $sql = "select cidr from routed where cidr >>= '$webvar{block}'"; 1122 } 1123 # I define there to be no errors on this operation... so we don't need to check for them. 1124 $sth = $ip_dbh->prepare($sql); 1125 $sth->execute; 1126 $sth->bind_columns(\$cblock); 1127 $sth->fetch(); 1128 $sth->finish; 1129 $page->param(backblock => $cblock); 766 $cblock = blockParent($ip_dbh, $webvar{block}); 767 } 768 $page->param(backblock => $cblock->{cidr}); 769 770 # Do some HTML fiddling here instead of using ESCAPE=HTML in the template, 771 # because otherwise we can't convert \n to <br>. *sigh* 772 $webvar{notes} = $q->escapeHTML($webvar{notes}); # escape first... 773 $webvar{notes} =~ s/\n/<br>\n/; # ... then convert newlines 774 $webvar{privdata} = ($webvar{privdata} ? $q->escapeHTML($webvar{privdata}) : " "); 775 $webvar{privdata} =~ s/\n/<br>\n/; 1130 776 1131 777 $page->param(cidr => $webvar{block}); … … 1134 780 $page->param(custid => $webvar{custid}); 1135 781 $page->param(swip => $webvar{swip} eq 'on' ? 'Yes' : 'No'); 1136 $page->param(circid => $q->escapeHTML($webvar{circid})); 1137 $page->param(desc => $q->escapeHTML($webvar{desc})); 1138 $page->param(notes => $q->escapeHTML($webvar{notes})); 1139 $webvar{privdata} = ($webvar{privdata} ? $q->escapeHTML($webvar{privdata}) : " "); 782 $page->param(circid => $webvar{circid}); 783 $page->param(desc => $webvar{desc}); 784 $page->param(notes => $webvar{notes}); 1140 785 $page->param(privdata => $webvar{privdata}) 1141 786 if $IPDBacl{$authuser} =~ /s/; … … 1157 802 } 1158 803 1159 my ($cidr, $custid, $type, $city, $circid, $desc, $notes, $alloctype, $privdata);804 my $blockdata; 1160 805 1161 806 if ($webvar{alloctype} eq 'rm') { 1162 $sth = $ip_dbh->prepare("select cidr,city from routed where cidr='$webvar{block}'"); 1163 $sth->execute(); 1164 1165 # This feels... extreme. 1166 croak $sth->errstr() if($sth->errstr()); 1167 1168 $sth->bind_columns(\$cidr,\$city); 1169 $sth->execute(); 1170 $sth->fetch || croak $sth->errstr(); 1171 $custid = "N/A"; 1172 $alloctype = $webvar{alloctype}; 1173 $circid = "N/A"; 1174 $desc = "N/A"; 1175 $notes = "N/A"; 1176 $privdata = "N/A"; 807 808 $blockdata->{block} = $webvar{block}; 809 $blockdata->{city} = getRoutedCity($ip_dbh, $webvar{block}); 810 $blockdata->{custid} = "N/A"; 811 $blockdata->{type} = $webvar{alloctype}; 812 $blockdata->{circuitid} = "N/A"; 813 $blockdata->{description} = "N/A"; 814 $blockdata->{notes} = "N/A"; 815 $blockdata->{privdata} = "N/A"; 1177 816 1178 817 } elsif ($webvar{alloctype} eq 'mm') { 1179 818 1180 $cidr = $webvar{block}; 1181 $city = "N/A"; 1182 $custid = "N/A"; 1183 $alloctype = $webvar{alloctype}; 1184 $circid = "N/A"; 1185 $desc = "N/A"; 1186 $notes = "N/A"; 1187 $privdata = "N/A"; 1188 1189 } elsif ($webvar{alloctype} =~ /^.i$/) { # done with alloctype=[rm]m 1190 1191 # Unassigning a static IP 1192 my $sth = $ip_dbh->prepare("select ip,custid,city,type,notes,circuitid,privdata". 1193 " from poolips where ip='$webvar{block}'"); 1194 $sth->execute(); 1195 # croak $sth->errstr() if($sth->errstr()); 1196 1197 $sth->bind_columns(\$cidr, \$custid, \$city, \$alloctype, \$notes, \$circid, 1198 \$privdata); 1199 $sth->fetch() || croak $sth->errstr; 1200 1201 } else { # done with alloctype=~ /^.i$/ 1202 1203 my $sth = $ip_dbh->prepare("select cidr,custid,type,city,circuitid,description,notes,privdata". 1204 " from allocations where cidr='$webvar{block}'"); 1205 $sth->execute(); 1206 # croak $sth->errstr() if($sth->errstr()); 1207 1208 $sth->bind_columns(\$cidr, \$custid, \$alloctype, \$city, \$circid, \$desc, 1209 \$notes, \$privdata); 1210 $sth->fetch() || carp $sth->errstr; 819 $blockdata->{block} = $webvar{block}; 820 $blockdata->{city} = "N/A"; 821 $blockdata->{custid} = "N/A"; 822 $blockdata->{type} = $webvar{alloctype}; 823 $blockdata->{circuitid} = "N/A"; 824 $blockdata->{description} = "N/A"; 825 $blockdata->{notes} = "N/A"; 826 $blockdata->{privdata} = "N/A"; 827 828 } else { 829 830 $blockdata = getBlockData($ip_dbh, $webvar{block}) 831 1211 832 } # end cases for different alloctypes 1212 833 1213 $page->param(block => $cidr); 1214 $page->param(disptype => $disp_alloctypes{$alloctype}); 1215 $page->param(type => $alloctype); 1216 $page->param(city => $city); 1217 $page->param(custid => $custid); 1218 $page->param(circid => $circid); 1219 $page->param(desc => $desc); 1220 $page->param(notes => $notes); 1221 $privdata = ' ' if $privdata eq ''; 1222 $page->param(privdata => $privdata) if $IPDBacl{$authuser} =~ /s/; 1223 $page->param(delpool => $alloctype =~ /^.[pd]$/); 834 $page->param(block => $blockdata->{block}); 835 $page->param(disptype => $disp_alloctypes{$blockdata->{type}}); 836 $page->param(type => $blockdata->{type}); 837 $page->param(city => $blockdata->{city}); 838 $page->param(custid => $blockdata->{custid}); 839 $page->param(circid => $blockdata->{circuitid}); 840 $page->param(desc => $blockdata->{description}); 841 $blockdata->{notes} = $q->escapeHTML($blockdata->{notes}); 842 $blockdata->{notes} =~ s/\n/<br>\n/; 843 $page->param(notes => $blockdata->{notes}); 844 $blockdata->{privdata} = $q->escapeHTML($blockdata->{privdata}); 845 $blockdata->{privdata} = ' ' if !$blockdata->{privdata}; 846 $blockdata->{privdata} =~ s/\n/<br>\n/; 847 $page->param(privdata => $blockdata->{privdata}) if $IPDBacl{$authuser} =~ /s/; 848 $page->param(delpool => $blockdata->{type} =~ /^.[pd]$/); 1224 849 1225 850 } # end remove() … … 1237 862 1238 863 # need to retrieve block data before deleting so we can notify on that 1239 my ($cidr,$custid,$type,$city,$description)= getBlockData($ip_dbh, $webvar{block});864 my $blockinfo = getBlockData($ip_dbh, $webvar{block}); 1240 865 1241 866 my ($code,$msg) = deleteBlock($ip_dbh, $webvar{block}, $webvar{alloctype}); … … 1243 868 $page->param(block => $webvar{block}); 1244 869 if ($code eq 'OK') { 1245 syslog "notice", "$authuser deallocated '$webvar{alloctype}'-type netblock $webvar{block} ".1246 " $custid, $city, desc='$description'";870 syslog "notice", "$authuser deallocated '$webvar{alloctype}'-type netblock $webvar{block} ". 871 $blockinfo->{custid}.", ".$blockinfo->{city}.", desc='".$blockinfo->{description}."'"; 1247 872 mailNotify($ip_dbh, 'da', "REMOVED: $disp_alloctypes{$webvar{alloctype}} $webvar{block}", 1248 873 "$disp_alloctypes{$webvar{alloctype}} $webvar{block} deallocated by $authuser\n". 1249 "CustID: $custid\nCity: $city\nDescription: $description\n"); 874 "CustID: ".$blockinfo->{custid}."\nCity: ".$blockinfo->{city}. 875 "\nDescription: ".$blockinfo->{description}."\n"); 1250 876 } else { 1251 877 $page->param(failmsg => $msg); -
branches/stable/cgi-bin/search.cgi
r593 r594 146 146 my $cols = "cidr,custid,type,city,description"; 147 147 148 # hack fix for undefined variables 149 $webvar{custid} = '' if !$webvar{custid}; 150 $webvar{desc} = '' if !$webvar{desc}; 151 $webvar{notes} = '' if !$webvar{notes}; 152 $webvar{custexclude} = '' if !$webvar{custexclude}; 153 $webvar{descexclude} = '' if !$webvar{descexclude}; 154 $webvar{notesexclude} = '' if !$webvar{notesexclude}; 155 148 156 # First chunk of SQL. Filter on custid, description, and notes as necessary. 149 my $sql = "(select $cols from searchme where".150 " $webvar{custexclude} (custid ilike '%$webvar{custid}%'". 151 " $sqlconcat (select $cols from searchme where $webvar{descexclude} description ilike '%$webvar{desc}%')". 152 " $sqlconcat (select $cols from searchme where $webvar{notesexclude} notes ilike '%$webvar{notes}%')";157 my $sql = qq(SELECT $cols FROM searchme\n); 158 $sql .= " WHERE $webvar{custexclude} (custid ~ '$webvar{custid}')\n"; 159 $sql .= " $sqlconcat (select $cols from searchme where $webvar{descexclude} description ~ '$webvar{desc}')\n"; 160 $sql .= " $sqlconcat (select $cols from searchme where $webvar{notesexclude} notes ~ '$webvar{notes}')"; 153 161 154 162 # If we're not supposed to search for all types, search for the selected types. 163 $webvar{alltypes} = '' if !$webvar{alltypes}; 164 $webvar{typeexclude} = '' if !$webvar{typeexclude}; 155 165 if ($webvar{alltypes} ne 'on') { 156 166 $sql .= " $sqlconcat (select $cols from searchme where $webvar{typeexclude} type in ("; … … 164 174 # If we're not supposed to search for all cities, search for the selected cities. 165 175 # This could be vastly improved with proper foreign keys in the database. 176 $webvar{allcities} = '' if !$webvar{allcities}; 177 $webvar{cityexclude} = '' if !$webvar{cityexclude}; 166 178 if ($webvar{allcities} ne 'on') { 167 179 $sql .= " $sqlconcat (select $cols from searchme where $webvar{cityexclude} city in ("; … … 315 327 # Creates appropriate SQL to run the search and display the results 316 328 # with queryResults() 317 sub viewBy ($$){329 sub viewBy { 318 330 my ($category,$query) = @_; 319 331 … … 445 457 # Display search queries based on the passed SQL. 446 458 # Takes SQL, page number (for multipage search results), and a total count. 447 sub queryResults ($$$){459 sub queryResults { 448 460 my ($sql, $pageNo, $rowCount) = @_; 449 461 my $offset = 0; … … 529 541 # Return count of rows to be returned in a "real" query 530 542 # with the passed SQL statement 531 sub countRows ($){543 sub countRows { 532 544 # Note that the "as foo" is required 533 545 my $sth = $ip_dbh->prepare("select count(*) from ($_[0]) as foo");
Note:
See TracChangeset
for help on using the changeset viewer.