Changeset 594 for branches/stable/cgi-bin/IPDB.pm
- Timestamp:
- 05/15/13 16:17:00 (11 years ago)
- Location:
- branches/stable
- Files:
-
- 2 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/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
Note:
See TracChangeset
for help on using the changeset viewer.