Changeset 125 for branches/stable/cgi-bin/main.cgi
- Timestamp:
- 01/14/05 18:03:44 (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/cgi-bin/main.cgi
r124 r125 14 14 use DBI; 15 15 use CommonWeb qw(:ALL); 16 use IPDB qw(:ALL);16 use IPDB 2.0 qw(:ALL); 17 17 use CustIDCK; 18 18 use POSIX qw(ceil); … … 33 33 syslog "debug", "$authuser active"; 34 34 35 checkDBSanity(); 35 # Why not a global DB handle? (And a global statement handle, as well...) 36 # Use the connectDB function, otherwise we end up confusing ourselves 37 my $ip_dbh; 38 my $sth; 39 my $errstr; 40 ($ip_dbh,$errstr) = connectDB("ipdb", "ipdb", "ipdbpwd"); 41 if (!$ip_dbh) { 42 printAndExit("Failed to connect to database: $errstr\n"); 43 } 44 checkDBSanity($ip_dbh); 45 initIPDBGlobals($ip_dbh); 36 46 37 47 #prototypes … … 48 58 49 59 # Stuff that gets loaded from the database 50 my @masterblocks; 51 my @citylist; 52 my @poplist; 53 my %disp_alloctypes; 54 my %list_alloctypes; 55 my %allocated; # Count for allocated blocks in a master block 56 my %free; # Count for free blocks (routed and unrouted) in a master block 57 my %bigfree; # Tracking largest free block in a master block 58 my %routed; # Number of routed blocks in a master block 59 60 # Why not a global DB handle? (And a global statement handle, as well...) 61 # We already know the DB is happy, (checkDBSanity) otherwise we wouldn't be here. 62 # Use the connectDB function, otherwise we end up confusing ourselves 63 my $ip_dbh = connectDB; 64 my $sth; 60 #my @citylist; 61 #my @poplist; 62 #my %allocated; # Count for allocated blocks in a master block 63 #my %free; # Count for free blocks (routed and unrouted) in a master block 64 #my %bigfree; # Tracking largest free block in a master block 65 #my %routed; # Number of routed blocks in a master block 65 66 66 67 # Slurp up the master block list - we need this several places 67 68 # While we're at it, initialize the related hashes. 68 $sth = $ip_dbh->prepare("select * from masterblocks order by cidr"); 69 $sth->execute; 70 for (my $i=0; my @data = $sth->fetchrow_array(); $i++) { 71 $masterblocks[$i] = new NetAddr::IP $data[0]; 72 $allocated{"$masterblocks[$i]"} = 0; 73 $free{"$masterblocks[$i]"} = 0; 74 $bigfree{"$masterblocks[$i]"} = 128; # Larger number means smaller block. 75 # Set to 128 to prepare for IPv6 76 $routed{"$masterblocks[$i]"} = 0; 77 } 78 79 # Initialize the city and poplist arrays 80 $sth = $ip_dbh->prepare("select * from cities order by city"); 81 $sth->execute; 82 my $i = 0; 83 my $j = 0; 84 while (my @data = $sth->fetchrow_array) { 85 $citylist[$i++] = $data[0]; 86 if ($data[1] eq 'y') { 87 $poplist[$j++] = $data[0]; 88 } 89 } 90 91 # Initialize alloctypes hashes 92 $sth = $ip_dbh->prepare("select * from alloctypes order by listorder"); 93 $sth->execute; 94 while (my @data = $sth->fetchrow_array) { 95 $disp_alloctypes{$data[0]} = $data[2]; 96 if ($data[3] < 900) { 97 $list_alloctypes{$data[0]} = $data[1]; 98 } 99 } 69 #$sth = $ip_dbh->prepare("select * from masterblocks order by cidr"); 70 #$sth->execute; 71 #for (my $i=0; my @data = $sth->fetchrow_array(); $i++) { 72 # $masterblocks[$i] = new NetAddr::IP $data[0]; 73 # $allocated{"$masterblocks[$i]"} = 0; 74 # $free{"$masterblocks[$i]"} = 0; 75 # $bigfree{"$masterblocks[$i]"} = 128; # Larger number means smaller block. 76 # # Set to 128 to prepare for IPv6 77 # $routed{"$masterblocks[$i]"} = 0; 78 #} 79 100 80 101 81 … … 114 94 my $cidr = new NetAddr::IP $webvar{cidr}; 115 95 116 print "<div type=heading align=center>Adding $cidr as master block.... \n";96 print "<div type=heading align=center>Adding $cidr as master block....</div>\n"; 117 97 118 98 # Allow transactions, and raise an exception on errors so we can catch it later. … … 142 122 eval { $ip_dbh->rollback; }; 143 123 syslog "err", "Could not add master block '$webvar{cidr}' to database: '$@'"; 144 print AndExit("Could not add master block $webvar{cidr} to database: $@");145 } 146 147 print "Success!</div>\n";148 149 printFooter; 124 printError("Could not add master block $webvar{cidr} to database: $@"); 125 } else { 126 print "<div type=heading align=center>Success!</div>\n"; 127 syslog "info", "$authuser added master block $webvar{cidr}"; 128 } 129 150 130 } # end add new master 151 131 … … 169 149 viewBy($webvar{searchfor}, $webvar{input}); 170 150 } 171 printFooter();172 151 } 173 152 … … 208 187 printAndExit("Error $boing: ".$excuses[$rnd/30.0]); 209 188 } 210 211 212 #end main() 213 214 # Shut up error log warning about not disconnecting. Maybe. 215 $ip_dbh->disconnect; 216 # Just in case something waaaayyy down isn't in place properly... 217 exit 0; 189 ## Finally! Done with that NASTY "case" emulation! 190 191 192 193 # Clean up IPDB globals, DB handle, etc. 194 finish($ip_dbh); 195 # We print the footer here, so we don't have to do it elsewhere. 196 printFooter; 197 # Just in case something waaaayyy down isn't in place 198 # properly... we exit explicitly. 199 exit; 200 218 201 219 202 … … 314 297 } else { 315 298 # This shouldn't happen, but if it does, whoever gets it deserves what they get... 316 print AndExit("Invalid query.");299 printError("Invalid query."); 317 300 } 318 301 } else { 319 302 # This shouldn't happen, but if it does, whoever gets it deserves what they get... 320 print AndExit("Invalid searchfor.");303 printError("Invalid searchfor."); 321 304 } 322 305 } # viewBy … … 425 408 426 409 # Initial display: Show master blocks with total allocated subnets, total free subnets 427 sub showSummary 428 { 410 sub showSummary { 411 # this is horrible-ugly-bad and will Go Away real soon now(TM) 429 412 print "Content-type: text/html\n\n"; 430 413 … … 432 415 'Free netblocks', 'Largest free block'); 433 416 434 # Snag the allocations. 435 # I think it's too confusing to leave out internal allocations. 436 $sth = $ip_dbh->prepare("select * from allocations"); 437 $sth->execute(); 438 while (my @data = $sth->fetchrow_array()) { 439 # cidr,custid,type,city,description 440 # We only need the cidr 441 my $cidr = new NetAddr::IP $data[0]; 442 foreach my $master (@masterblocks) { 443 if ($master->contains($cidr)) { 444 $allocated{"$master"}++; 445 } 446 } 447 } 448 449 # Snag routed blocks 450 $sth = $ip_dbh->prepare("select * from routed"); 451 $sth->execute(); 452 while (my @data = $sth->fetchrow_array()) { 453 # cidr,maskbits,city 454 # We only need the cidr 455 my $cidr = new NetAddr::IP $data[0]; 456 foreach my $master (@masterblocks) { 457 if ($master->contains($cidr)) { 458 $routed{"$master"}++; 459 } 460 } 461 } 462 463 # Snag the free blocks. 464 $sth = $ip_dbh->prepare("select * from freeblocks"); 465 $sth->execute(); 466 while (my @data = $sth->fetchrow_array()) { 467 # cidr,maskbits,city 468 # We only need the cidr 469 my $cidr = new NetAddr::IP $data[0]; 470 foreach my $master (@masterblocks) { 471 if ($master->contains($cidr)) { 472 $free{"$master"}++; 473 if ($cidr->masklen < $bigfree{"$master"}) { $bigfree{"$master"} = $cidr->masklen; } 474 } 475 } 476 } 477 478 # Print the data. 417 my %allocated; 418 my %free; 419 my %routed; 420 my %bigfree; 421 422 # Count the allocations. 423 $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?"); 424 foreach my $master (@masterblocks) { 425 $sth->execute("$master"); 426 $sth->bind_columns(\$allocated{"$master"}); 427 $sth->fetch(); 428 } 429 430 # Count routed blocks 431 $sth = $ip_dbh->prepare("select count(*) from routed where cidr <<= ?"); 432 foreach my $master (@masterblocks) { 433 $sth->execute("$master"); 434 $sth->bind_columns(\$routed{"$master"}); 435 $sth->fetch(); 436 } 437 438 # Count the free blocks. 439 $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ?"); 440 foreach my $master (@masterblocks) { 441 $sth->execute("$master"); 442 $sth->bind_columns(\$free{"$master"}); 443 $sth->fetch(); 444 } 445 446 # Find the largest free block in each master 447 $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? order by maskbits limit 1"); 448 foreach my $master (@masterblocks) { 449 $sth->execute("$master"); 450 $sth->bind_columns(\$bigfree{"$master"}); 451 $sth->fetch(); 452 } 453 454 # Print the data. 479 455 my $count=0; 480 456 foreach my $master (@masterblocks) { … … 492 468 print "Note: Free blocks noted here include both routed and unrouted blocks.\n"; 493 469 494 # Because of the way this sub gets called, we don't need to print the footer here.495 # (index.shtml makes an SSI #include call to cgi-bin/main.cgi?action=index)496 # If we do, the footer comes in twice...497 #printFooter;498 470 } # showSummary 499 471 … … 510 482 qq($webvar{block}:</div></center><br>\n); 511 483 484 my %allocated; 485 my %free; 486 my %routed; 487 my %bigfree; 488 512 489 my $master = new NetAddr::IP $webvar{block}; 513 490 my @localmasters; 514 491 515 $sth = $ip_dbh->prepare("select * from routed order by cidr"); 492 # Fetch only the blocks relevant to this master 493 $sth = $ip_dbh->prepare("select * from routed where cidr <<= '$master' order by cidr"); 516 494 $sth->execute(); 517 495 … … 519 497 while (my @data = $sth->fetchrow_array()) { 520 498 my $cidr = new NetAddr::IP $data[0]; 521 if ($master->contains($cidr)) {522 $localmasters[$i++] = $cidr;523 $free{"$cidr"} = 0;524 $allocated{"$cidr"} = 0;499 $localmasters[$i++] = $cidr; 500 $free{"$cidr"} = 0; 501 $allocated{"$cidr"} = 0; 502 $bigfree{"$cidr"} = 128; 525 503 # Retain the routing destination 526 $routed{"$cidr"} = $data[2]; 527 } 528 } 529 530 # Check if there were actually any blocks routed from this master 504 $routed{"$cidr"} = $data[2]; 505 } 506 507 # Check if there were actually any blocks routed from this master 531 508 if ($i > 0) { 532 509 startTable('Routed block','Routed to','Allocated blocks', 533 510 'Free blocks','Largest free block'); 534 511 535 # Count the allocations 536 $sth = $ip_dbh->prepare("select * from allocations"); 537 $sth->execute(); 538 while (my @data = $sth->fetchrow_array()) { 539 # cidr,custid,type,city,description 540 # We only need the cidr 541 my $cidr = new NetAddr::IP $data[0]; 542 foreach my $master (@localmasters) { 543 if ($master->contains($cidr)) { 544 $allocated{"$master"}++; 545 } 546 } 547 } 548 549 # initialize bigfree base points 550 foreach my $lmaster (@localmasters) { 551 $bigfree{"$lmaster"} = 128; 552 } 553 554 # Snag the free blocks. 555 $sth = $ip_dbh->prepare("select * from freeblocks"); 556 $sth->execute(); 557 while (my @data = $sth->fetchrow_array()) { 558 # cidr,maskbits,city 559 # We only need the cidr 560 my $cidr = new NetAddr::IP $data[0]; 561 foreach my $lmaster (@localmasters) { 562 if ($lmaster->contains($cidr)) { 563 $free{"$lmaster"}++; 564 if ($cidr->masklen < $bigfree{"$lmaster"}) { 565 $bigfree{"$lmaster"} = $cidr->masklen; 566 } 567 } 568 # check for largest free block 569 } 512 # Count the allocations 513 $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?"); 514 foreach my $master (@localmasters) { 515 $sth->execute("$master"); 516 $sth->bind_columns(\$allocated{"$master"}); 517 $sth->fetch(); 518 } 519 520 # Count the free blocks. 521 $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ?"); 522 foreach my $master (@localmasters) { 523 $sth->execute("$master"); 524 $sth->bind_columns(\$free{"$master"}); 525 $sth->fetch(); 526 } 527 528 # Get the size of the largest free block 529 $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? order by maskbits limit 1"); 530 foreach my $master (@localmasters) { 531 $sth->execute("$master"); 532 $sth->bind_columns(\$bigfree{"$master"}); 533 $sth->fetch(); 570 534 } 571 535 … … 603 567 # Snag the free blocks. 604 568 my $count = 0; 605 $sth = $ip_dbh->prepare("select * from freeblocks where routed='n' order by cidr"); 569 $sth = $ip_dbh->prepare("select cidr from freeblocks where cidr <<='$master' and ". 570 "routed='n' order by cidr"); 606 571 $sth->execute(); 607 572 while (my @data = $sth->fetchrow_array()) { 608 # cidr,maskbits,city609 # We only need the cidr610 573 my $cidr = new NetAddr::IP $data[0]; 611 if ($master->contains($cidr)) { 612 my @row = ("$cidr", $cidr->range); 613 printRow(\@row, 'color1' ) if($count%2==0); 614 printRow(\@row, 'color2' ) if($count%2!=0); 615 $count++; 616 } 574 my @row = ("$cidr", $cidr->range); 575 printRow(\@row, 'color1' ) if($count%2==0); 576 printRow(\@row, 'color2' ) if($count%2!=0); 577 $count++; 617 578 } 618 579 619 580 print "</table>\n"; 620 printFooter;621 581 } # showMaster 622 582 … … 641 601 qq($master ($data[2]):</div></center><br>\n); 642 602 643 $sth = $ip_dbh->prepare("select * from allocations order by cidr"); 603 startTable('CIDR allocation','Customer Location','Type','CustID','Description/Name'); 604 605 # Snag the allocations for this block 606 $sth = $ip_dbh->prepare("select * from allocations where cidr <<= '$master' order by cidr"); 644 607 $sth->execute(); 645 646 startTable('CIDR allocation','Customer Location','Type','CustID','Description/Name');647 608 648 609 my $count=0; 649 610 while (my @data = $sth->fetchrow_array()) { 650 # cidr,custid,type,city,description,notes,maskbits 611 # cidr,custid,type,city,description,notes,maskbits,circuitid 651 612 my $cidr = new NetAddr::IP $data[0]; 652 if (!$master->contains($cidr)) { next; }653 613 654 614 # Clean up extra spaces that are borking things. … … 691 651 # unrouted free blocks, but it's better to let the database do the work if we can. 692 652 $count = 0; 693 $sth = $ip_dbh->prepare("select * from freeblocks where routed='y' order by cidr");653 $sth = $ip_dbh->prepare("select * from freeblocks where routed='y' and cidr <<= '$master' order by cidr"); 694 654 $sth->execute(); 695 655 while (my @data = $sth->fetchrow_array()) { 696 656 # cidr,maskbits,city 697 657 my $cidr = new NetAddr::IP $data[0]; 698 if ($master->contains($cidr)) { 699 my @row = ("<a href=\"/ip/cgi-bin/main.cgi?action=assign&block=$cidr\">$cidr</a>", 658 my @row = ("<a href=\"/ip/cgi-bin/main.cgi?action=assign&block=$cidr\">$cidr</a>", 700 659 $cidr->range); 701 printRow(\@row, 'color1') if ($count%2 == 0); 702 printRow(\@row, 'color2') if ($count%2 != 0); 703 $count++; 704 } 660 printRow(\@row, 'color1') if ($count%2 == 0); 661 printRow(\@row, 'color2') if ($count%2 != 0); 662 $count++; 705 663 } 706 664 707 665 print "</table>\n"; 708 printFooter;709 666 } # showRBlock 710 667 … … 762 719 print "</table>\n"; 763 720 764 printFooter;765 721 } # end listPool 766 722 767 723 768 # Should this maybe just be a full static page? It just spews out some predefined HTML. 724 # Show "Add new allocation" page. Note that the actual page may 725 # be one of two templates, and the lists come from the database. 769 726 sub assignBlock { 770 727 printHeader(''); … … 824 781 print $html; 825 782 826 printFooter();827 783 } # assignBlock 828 784 … … 837 793 # Going to manually validate some items. 838 794 # custid and city are automagic. 839 validateInput(); 840 841 # This isn't always useful. 842 # if (!$webvar{maskbits}) { 843 # printAndExit("Please enter a CIDR block length."); 844 # } 795 return if !validateInput(); 845 796 846 797 # Several different cases here. … … 860 811 " ptype='$base' and (city='Sudbury' or city='North Bay')"; 861 812 } else { 862 ## $city doesn't seem to get defined here.863 my $city; # Shut up Perl's "strict" scoping/usage check.864 813 $sql = "select * from poolips where available='y' and". 865 814 " ptype='$base' and city='$webvar{pop}'"; … … 891 840 892 841 if (!$webvar{maskbits}) { 893 printAndExit("Please specify a CIDR mask length."); 842 printError("Please specify a CIDR mask length."); 843 return; 894 844 } 895 845 my $sql; … … 908 858 " a set of smaller netblocks or a single smaller netblock."; 909 859 } else { 860 ##fixme 861 # This section needs serious Pondering. 910 862 if ($webvar{alloctype} =~ /^[cdsmw]p$/) { 911 863 if (($webvar{city} !~ /^(Sudbury|North Bay)$/) && ($webvar{alloctype} eq 'dp')) { 912 printAndExit("You must chose Sudbury or North Bay for DSL pools."); } 864 printError("You must chose Sudbury or North Bay for DSL pools."); 865 return; 866 } 913 867 $city = $webvar{city}; 914 868 $failmsg = "No suitable free block found.<br>\nYou will have to route another". 915 " superblock <br>\nfrom one of themaster blocks in Sudbury or chose a smaller".869 " superblock from one of the<br>\nmaster blocks in Sudbury or chose a smaller". 916 870 " block size for the pool."; 917 871 } else { … … 933 887 my @data = $sth->fetchrow_array(); 934 888 if ($data[0] eq "") { 935 printAndExit($failmsg); 889 printError($failmsg); 890 return; 936 891 } 937 892 $cidr = new NetAddr::IP $data[0]; … … 982 937 print $html; 983 938 984 printFooter;985 939 } # end confirmAssign 986 940 … … 990 944 # Some things are done more than once. 991 945 printHeader(''); 992 validateInput(); 993 994 # Set some things that may be needed 995 # Don't set $cidr here as it may not even be a valid IP address. 996 my $alloc_from = new NetAddr::IP $webvar{alloc_from}; 997 998 # dynDSL (dy), sIP DSL(dp), and server pools (sp) are nominally allocated to Sudbury 999 # no matter what else happens. 1000 # if ($webvar{alloctype} =~ /^([sd]p|dy)$/) { $webvar{city} = "Sudbury"; } 1001 # OOPS. forgot about North Bay DSL. 1002 #### Gotta make this cleaner and more accurate 1003 # if ($webvar{alloctype} eq "sp") { $webvar{city} = "Sudbury"; } 1004 1005 # Same ordering as confirmation page 1006 1007 if ($webvar{alloctype} =~ /^[cdsmw]i$/) { 1008 my ($base,$tmp) = split //, $webvar{alloctype}; # split into individual chars 1009 1010 # We'll just have to put up with the oddities caused by SQL (un)sort order 1011 $sth = $ip_dbh->prepare("select * from poolips where pool='$webvar{alloc_from}'". 1012 " and available='y' order by ip"); 1013 $sth->execute; 1014 1015 my @data = $sth->fetchrow_array; 1016 my $cidr = $data[1]; 1017 1018 $sth = $ip_dbh->prepare("update poolips set custid='$webvar{custid}',". 1019 "city='$webvar{city}',available='n',description='$webvar{desc}',". 1020 "circuitid='$webvar{circid}'". 1021 " where ip='$cidr'"); 1022 $sth->execute; 1023 if ($sth->err) { 1024 syslog "err", "Allocation of $cidr to $webvar{custid} by $authuser failed: ". 1025 "'".$sth->errstr."'"; 1026 printAndExit("Allocation of $cidr to $webvar{custid} failed: '".$sth->errstr."'"); 1027 } 1028 print qq(<div class="center"><div class="heading">The IP $cidr has been allocated to customer $webvar{custid}</div></div>); 1029 syslog "notice", "$authuser allocated $cidr to $webvar{custid}"; 1030 # Notify tech@example.com 1031 mailNotify('tech@example.com',"$disp_alloctypes{$webvar{alloctype}} allocation", 1032 "$disp_alloctypes{$webvar{alloctype}} $cidr allocated to customer $webvar{custid}\n". 1033 "Description: $webvar{desc}\n\nAllocated by: $authuser\n"); 1034 1035 } else { # end IP-from-pool allocation 1036 1037 # Set $cidr here as it may not be a valid IP address elsewhere. 1038 my $cidr = new NetAddr::IP $webvar{fullcidr}; 1039 1040 # Allow transactions, and make errors much easier to catch. 1041 # Much as I would like to error-track specifically on each ->execute, 1042 # that's a LOT of code, and some SQL blocks MUST be atomic at a 1043 # multi-statement level. :/ 1044 local $ip_dbh->{AutoCommit} = 0; # These need to be local so we don't 1045 local $ip_dbh->{RaiseError} = 1; # step on our toes by accident. 1046 1047 if ($webvar{fullcidr} eq $webvar{alloc_from}) { 1048 # Easiest case- insert in one table, delete in the other, and go home. More or less. 1049 # insert into allocations values (cidr,custid,type,city,desc) and 1050 # delete from freeblocks where cidr='cidr' 1051 # For data safety on non-transaction DBs, we delete first. 1052 1053 eval { 1054 if ($webvar{alloctype} eq 'rr') { 1055 $sth = $ip_dbh->prepare("update freeblocks set routed='y',city='$webvar{city}'". 1056 " where cidr='$webvar{fullcidr}'"); 1057 $sth->execute; 1058 $sth = $ip_dbh->prepare("insert into routed values ('$webvar{fullcidr}',". 1059 $cidr->masklen.",'$webvar{city}')"); 1060 $sth->execute; 1061 } else { 1062 # common stuff for end-use, dialup, dynDSL, pools, etc, etc. 1063 1064 # city has to be reset for DSL/server pools; nominally to Sudbury. 1065 ## Gotta rethink this; DSL pools can be in North Bay as well. :/ 1066 #if ($webvar{alloctype} =~ /^[sd]p$/) { $webvar{city} = 'Sudbury'; } 1067 1068 $sth = $ip_dbh->prepare("delete from freeblocks where cidr='$webvar{fullcidr}'"); 1069 $sth->execute; 1070 1071 $sth = $ip_dbh->prepare("insert into allocations values ('$webvar{fullcidr}',". 1072 "'$webvar{custid}','$webvar{alloctype}','$webvar{city}','$webvar{desc}',". 1073 "'$webvar{notes}',".$cidr->masklen.",'$webvar{circid}')"); 1074 $sth->execute; 1075 } # routing vs non-routing netblock 1076 $ip_dbh->commit; 1077 }; # end of eval 1078 if ($@) { 1079 carp "Transaction aborted because $@"; 1080 eval { $ip_dbh->rollback; }; 1081 syslog "err", "Allocation of '$webvar{fullcidr}' to '$webvar{custid}' as ". 1082 "'$webvar{alloctype}' by $authuser failed: '$@'"; 1083 printAndExit("Allocation of $cidr as $disp_alloctypes{$webvar{alloctype}} failed.\n"); 1084 } 1085 1086 # If we get here, the DB transaction has succeeded. 1087 syslog "notice", "$authuser allocated '$webvar{fullcidr}' to '$webvar{custid}' as '$webvar{alloctype}'"; 1088 1089 # How to log SQL without munging too many error-checking wrappers in? 1090 # syslog "info", " 1091 # We don't. GRRR. 1092 1093 } else { # webvar{fullcidr} != webvar{alloc_from} 1094 # Hard case. Allocation is smaller than free block. 1095 my $wantmaskbits = $cidr->masklen; 1096 my $maskbits = $alloc_from->masklen; 1097 1098 my @newfreeblocks; # Holds free blocks generated from splitting the source freeblock. 1099 1100 my $i=0; 1101 while ($maskbits++ < $wantmaskbits) { 1102 my @subblocks = $alloc_from->split($maskbits); 1103 $newfreeblocks[$i++] = $subblocks[1]; 1104 } # while 1105 1106 # Begin SQL transaction block 1107 eval { 1108 # Delete old freeblocks entry 1109 $sth = $ip_dbh->prepare("delete from freeblocks where cidr='$webvar{alloc_from}'"); 1110 $sth->execute(); 1111 1112 # now we have to do some magic for routing blocks 1113 if ($webvar{alloctype} eq 'rr') { 1114 # Insert the new freeblocks entries 1115 # Note that non-routed blocks are assigned to <NULL> 1116 $sth = $ip_dbh->prepare("insert into freeblocks values (?, ?, '<NULL>','n')"); 1117 foreach my $block (@newfreeblocks) { 1118 $sth->execute("$block", $block->masklen); 1119 } 1120 # Insert the entry in the routed table 1121 $sth = $ip_dbh->prepare("insert into routed values ('$cidr',". 1122 $cidr->masklen.",'$webvar{city}')"); 1123 $sth->execute; 1124 # Insert the (almost) same entry in the freeblocks table 1125 $sth = $ip_dbh->prepare("insert into freeblocks values ('$cidr',". 1126 $cidr->masklen.",'$webvar{city}','y')"); 1127 $sth->execute; 1128 1129 } else { # done with alloctype == rr 1130 1131 # Insert the new freeblocks entries 1132 $sth = $ip_dbh->prepare("insert into freeblocks values (?, ?, (select city from routed where cidr >> '$cidr'),'y')"); 1133 foreach my $block (@newfreeblocks) { 1134 $sth->execute("$block", $block->masklen); 1135 } 1136 # Insert the allocations entry 1137 $sth = $ip_dbh->prepare("insert into allocations values ('$webvar{fullcidr}',". 1138 "'$webvar{custid}','$webvar{alloctype}','$webvar{city}',". 1139 "'$webvar{desc}','$webvar{notes}',".$cidr->masklen.",'$webvar{circid}')"); 1140 $sth->execute; 1141 } # done with netblock alloctype != rr 1142 $ip_dbh->commit; 1143 }; # end eval 1144 if ($@) { 1145 carp "Transaction aborted because $@"; 1146 eval { $ip_dbh->rollback; }; 1147 syslog "err", "Allocation of '$webvar{fullcidr}' to '$webvar{custid}' as ". 1148 "'$webvar{alloctype}' by $authuser failed: '$@'"; 1149 printAndExit("Allocation of $cidr as $disp_alloctypes{$webvar{alloctype}} failed.\n"); 1150 } 1151 syslog "notice", "$authuser allocated '$webvar{fullcidr}' to '$webvar{custid}' as '$webvar{alloctype}'"; 1152 1153 } # end fullcidr != alloc_from 1154 1155 # Begin SQL transaction block 1156 eval { 1157 # special extra handling for pools. 1158 # Note that this must be done for ANY pool allocation! 1159 if ( my ($pooltype) = ($webvar{alloctype} =~ /^([cdsmw])p$/) ) { 1160 # have to insert all pool IPs into poolips table as "unallocated". 1161 $sth = $ip_dbh->prepare("insert into poolips values ('$webvar{fullcidr}',". 1162 " ?, '6750400', '$webvar{city}', '$pooltype', 'y', '', '', '')"); 1163 my @poolip_list = $cidr->hostenum; 1164 for (my $i=1; $i<=$#poolip_list; $i++) { 1165 $sth->execute($poolip_list[$i]->addr); 1166 } 1167 } # end pool special 1168 $ip_dbh->commit; 1169 }; # end eval 1170 if ($@) { 1171 carp "Transaction aborted because $@"; 1172 eval { $ip_dbh->rollback; }; 1173 syslog "err", "Initialization of pool '$webvar{fullcidr}' by $authuser failed: '$@'"; 1174 printAndExit("$disp_alloctypes{$webvar{alloctype}} $webvar{fullcidr} not completely initialized."); 1175 } 1176 syslog "notice", "$disp_alloctypes{$webvar{alloctype}} '$webvar{fullcidr}' successfully initialized by $authuser"; 1177 1178 print qq(<div class="center"><div class="heading">The block $webvar{fullcidr} was sucessfully added as type '$webvar{alloctype}' ($disp_alloctypes{$webvar{alloctype}})</div></div>); 1179 1180 if ($webvar{alloctype} eq 'cn') { 946 return if !validateInput(); 947 948 # $code is "success" vs "failure", $msg contains OK for a 949 # successful netblock allocation, the IP allocated for static 950 # IP, or the error message if an error occurred. 951 my ($code,$msg) = allocateBlock($ip_dbh, $webvar{fullcidr}, $webvar{alloc_from}, 952 $webvar{custid}, $webvar{alloctype}, $webvar{city}, $webvar{desc}, $webvar{notes}, 953 $webvar{circid}); 954 955 if ($code eq 'OK') { 956 if ($webvar{alloctype} =~ /^.i$/) { 957 print qq(<div class="center"><div class="heading">The IP $msg has been allocated to customer $webvar{custid}</div></div>); 1181 958 # Notify tech@example.com 1182 959 mailNotify('tech@example.com',"$disp_alloctypes{$webvar{alloctype}} allocation", 1183 "$disp_alloctypes{$webvar{alloctype}} $ cidrallocated to customer $webvar{custid}\n".960 "$disp_alloctypes{$webvar{alloctype}} $msg allocated to customer $webvar{custid}\n". 1184 961 "Description: $webvar{desc}\n\nAllocated by: $authuser\n"); 1185 } 1186 1187 } # end static-IP vs netblock allocation 1188 1189 printFooter(); 962 } else { 963 print qq(<div class="center"><div class="heading">The block $webvar{fullcidr} was ). 964 "sucessfully added as type '$webvar{alloctype}' ". 965 "($disp_alloctypes{$webvar{alloctype}})</div></div>"; 966 } 967 syslog "notice", "$authuser allocated '$webvar{fullcidr}' to '$webvar{custid}' as ". 968 "'$webvar{alloctype}'"; 969 } else { 970 syslog "err", "Allocation of '$webvar{fullcidr}' to '$webvar{custid}' as ". 971 "'$webvar{alloctype}' by $authuser failed: '$msg'"; 972 printError("Allocation of $webvar{fullcidr} as $disp_alloctypes{$webvar{alloctype}}". 973 " failed: $msg\n"); 974 } 975 1190 976 } # end insertAssign() 1191 977 … … 1196 982 sub validateInput { 1197 983 if ($webvar{city} eq '-') { 1198 printAndExit("Please choose a city."); 984 printError("Please choose a city."); 985 return; 1199 986 } 1200 987 chomp $webvar{alloctype}; … … 1202 989 if ($webvar{alloctype} =~ /^(ci|di|cn|mi|wi)$/) { 1203 990 if (!$webvar{custid}) { 1204 printAndExit("Please enter a customer ID."); 991 printError("Please enter a customer ID."); 992 return; 1205 993 } 1206 994 if ($webvar{custid} !~ /^(?:\d{10}|\d{7}|STAFF)(?:-\d\d?)?$/) { … … 1209 997 # Crosscheck with ... er... something. 1210 998 my $status = CustIDCK->custid_exist($webvar{custid}); 1211 printAndExit("Error verifying customer ID: ".$CustIDCK::ErrMsg) 1212 if $CustIDCK::Error; 1213 printAndExit("Customer ID not valid. Make sure the Customer ID ". 1214 "is correct.<br>\nUse STAFF for staff static IPs, and 6750400 for any other ". 1215 "non-customer assignments.") 1216 if !$status; 999 if ($CustIDCK::Error) { 1000 printError("Error verifying customer ID: ".$CustIDCK::ErrMsg); 1001 return; 1002 } 1003 if (!$status) { 1004 printError("Customer ID not valid. Make sure the Customer ID ". 1005 "is correct.<br>\nUse STAFF for staff static IPs, and 6750400 for any other ". 1006 "non-customer assignments."); 1007 return; 1008 } 1217 1009 #"Please enter a valid customer ID- this must be a 7- or 10-digit number, or STAFF for 1218 1010 #static IPs for staff."); 1219 1011 } 1220 1012 # print "<!-- [ In validateInput(). Insert customer ID cross-check here. ] -->\n"; 1221 } elsif ($webvar{alloctype} =~ /^([cdsmw]p|si|dn|dy|dc|ee|rr|i i)$/){1013 } elsif ($webvar{alloctype} =~ /^([cdsmw]p|si|dn|dy|dc|ee|rr|in)$/){ 1222 1014 # All non-customer allocations MUST be entered with "our" customer ID. 1223 1015 # I have Defined this as 6750400 for consistency. … … 1226 1018 $webvar{custid} = "6750400"; 1227 1019 } 1228 if ($webvar{alloctype} eq 'rr') {1229 my $flag;1230 foreach (@poplist) {1231 if (/^$webvar{city}$/) {1232 $flag = 'y'; last;1233 }1234 }1235 if (!$flag) {1236 printAndExit("Please choose a valid POP location for a routed netblock. Valid ".1237 "POP locations are currently:<br>\n".join (" - ", @poplist));1238 }1239 }1240 1020 } else { 1241 1021 # Danger! Danger! alloctype should ALWAYS be set by a dropdown. Anyone 1242 1022 # managing to call things in such a way as to cause this deserves a cryptic error. 1243 printAndExit("Invalid alloctype"); 1244 } 1245 return 0; 1023 printError("Invalid alloctype"); 1024 return; 1025 } 1026 1027 # Check POP location 1028 my $flag; 1029 if ($webvar{alloctype} eq 'rr') { 1030 $flag = 'for a routed netblock'; 1031 foreach (@poplist) { 1032 if (/^$webvar{city}$/) { 1033 $flag = 'n'; 1034 last; 1035 } 1036 } 1037 } else { 1038 $flag = 'n'; 1039 if ($webvar{pop} =~ /^-$/) { 1040 $flag = 'to route the block from/through'; 1041 } 1042 } 1043 if ($flag ne 'n') { 1044 printError("Please choose a valid POP location $flag. Valid ". 1045 "POP locations are currently:<br>\n".join (" - ", @poplist)); 1046 return; 1047 } 1048 1049 return 'OK'; 1246 1050 } # end validateInput 1247 1051 … … 1318 1122 print $html; 1319 1123 1320 printFooter();1321 1124 } # edit() 1322 1125 … … 1352 1155 eval { $ip_dbh->rollback; }; 1353 1156 syslog "err", "$authuser could not update block/IP '$webvar{block}': '$@'"; 1354 printAndExit("Could not update block/IP $webvar{block}: $@"); 1157 printError("Could not update block/IP $webvar{block}: $@"); 1158 return; 1355 1159 } 1356 1160 … … 1358 1162 syslog "notice", "$authuser updated $webvar{block}"; 1359 1163 open (HTML, "../updated.html") 1360 1164 or croak "Could not open updated.html :$!"; 1361 1165 my $html = join('', <HTML>); 1362 1166 … … 1376 1180 print $html; 1377 1181 1378 printFooter;1379 1182 } # update() 1380 1183 1381 1184 1382 1185 # Delete an allocation. 1383 sub remove 1384 { 1186 sub remove { 1385 1187 printHeader(''); 1386 1188 #show confirm screen. … … 1392 1194 # Serves'em right for getting here... 1393 1195 if (!defined($webvar{block})) { 1394 printAndExit("Error 332"); 1196 printError("Error 332"); 1197 return; 1395 1198 } 1396 1199 … … 1466 1269 1467 1270 print $html; 1468 printFooter;1469 1271 } # end edit() 1470 1272 … … 1477 1279 printHeader(''); 1478 1280 1479 # Enable transactions and exception-on-errors... but only for this sub 1480 local $ip_dbh->{AutoCommit} = 0; 1481 local $ip_dbh->{RaiseError} = 1; 1482 1483 if ($webvar{alloctype} =~ /^[cdsmw]i$/) { 1484 1485 eval { 1486 $sth = $ip_dbh->prepare("select * from poolips where ip='$webvar{block}'"); 1487 $sth->execute; 1488 my @data = $sth->fetchrow_array; 1489 $sth = $ip_dbh->prepare("select city from allocations where cidr='$data[0]'"); 1490 $sth->execute; 1491 @data = $sth->fetchrow_array; 1492 $sth = $ip_dbh->prepare("update poolips set custid='6750400', available='y',". 1493 " city='$data[0]', description='', notes='', circuitid='' where ip='$webvar{block}'"); 1494 $sth->execute; 1495 $ip_dbh->commit; 1496 }; 1497 if ($@) { 1498 carp "Transaction aborted because $@"; 1499 eval { $ip_dbh->rollback; }; 1500 syslog "err", "$authuser could not deallocate static IP '$webvar{block}': '$@'"; 1501 printAndExit("Could not deallocate static IP $webvar{block}: $@"); 1502 } 1281 my ($code,$msg) = deleteBlock($ip_dbh, $webvar{block}, $webvar{alloctype}); 1282 1283 if ($code eq 'OK') { 1503 1284 print "<div class=heading align=center>Success! $webvar{block} deallocated.</div>\n"; 1504 syslog "notice", "$authuser deallocated static IP $webvar{block}";1505 1506 } elsif ($webvar{alloctype} eq 'mm') { # end alloctype = [cdsmw]i1507 1508 eval {1509 $sth = $ip_dbh->prepare("delete from masterblocks where cidr='$webvar{block}'");1510 $sth->execute;1511 $sth = $ip_dbh->prepare("delete from freeblocks where cidr='$webvar{block}'");1512 $sth->execute;1513 $ip_dbh->commit;1514 };1515 if ($@) {1516 carp "Transaction aborted because $@";1517 eval { $ip_dbh->rollback; };1518 syslog "err", "$authuser could not remove master block '$webvar{block}': '$@'";1519 printAndExit("Could not remove master block $webvar{block}: $@");1520 }1521 print "<div class=heading align=center>Success! Master $webvar{block} removed.</div>\n";1522 syslog "notice", "$authuser removed master block $webvar{block}";1523 1524 } else { # end alloctype master block case1525 1526 ## This is a big block; but it HAS to be done in a chunk. Any removal1527 ## of a netblock allocation may result in a larger chunk of free1528 ## contiguous IP space - which may in turn be combined into a single1529 ## netblock rather than a number of smaller netblocks.1530 1531 eval {1532 1533 my $cidr = new NetAddr::IP $webvar{block};1534 if ($webvar{alloctype} eq 'rr') {1535 1536 $sth = $ip_dbh->prepare("delete from routed where cidr='$webvar{block}'");1537 $sth->execute;1538 # Make sure block getting deleted is properly accounted for.1539 $sth = $ip_dbh->prepare("update freeblocks set routed='n',city='<NULL>'".1540 " where cidr='$webvar{block}'");1541 $sth->execute;1542 # Set up query to start compacting free blocks.1543 $sth = $ip_dbh->prepare("select * from freeblocks where ".1544 "maskbits<=".$cidr->masklen." and routed='n' order by maskbits desc");1545 1546 } else { # end alloctype routing case1547 1548 $sth = $ip_dbh->prepare("delete from allocations where cidr='$webvar{block}'");1549 $sth->execute;1550 # Special case - delete pool IPs1551 if ($webvar{alloctype} =~ /^[cdsmw]p$/) {1552 # We have to delete the IPs from the pool listing.1553 $sth = $ip_dbh->prepare("delete from poolips where pool='$webvar{block}'");1554 $sth->execute;1555 }1556 1557 # Set up query for compacting free blocks.1558 $sth = $ip_dbh->prepare("select * from freeblocks where cidr << ".1559 "(select cidr from routed where cidr >> '$cidr') ".1560 " and maskbits<=".$cidr->masklen." and routed='y' order by maskbits desc");1561 1562 } # end alloctype general case1563 1564 ##TEMP1565 ## Temporary wrapper to "properly" deallocate sIP PPPoE/DSL "netblocks" in 209.91.185.0/241566 my $staticpool = new NetAddr::IP "209.91.185.0/24";1567 ##TEMP1568 if ($cidr->within($staticpool)) {1569 ##TEMP1570 # We've already deleted the block, now we have to stuff its IPs into the pool.1571 $sth = $ip_dbh->prepare("insert into poolips values ('209.91.185.0/24',?,'6750400','Sudbury','d','y','','','')");1572 $sth->execute($cidr->addr);1573 foreach my $ip ($cidr->hostenum) {1574 $sth->execute("$ip");1575 }1576 $cidr--;1577 $sth->execute($cidr->addr);1578 1579 ##TEMP1580 } else {1581 ##TEMP1582 1583 # Now we look for larger-or-equal-sized free blocks in the same master (routed)1584 # (super)block. If there aren't any, we can't combine blocks anyway. If there1585 # are, we check to see if we can combine blocks.1586 # Execute the statement prepared in the if-else above.1587 1588 $sth->execute;1589 1590 # NetAddr::IP->compact() attempts to produce the smallest inclusive block1591 # from the caller and the passed terms.1592 # EG: if you call $cidr->compact($ip1,$ip2,$ip3) when $cidr, $ip1, $ip2,1593 # and $ip3 are consecutive /27's starting on .0 (.0-.31, .32-.63,1594 # .64-.95, and .96-.128), you will get an array containing a single1595 # /25 as element 0 (.0-.127). Order is not important; you could have1596 # $cidr=.32/27, $ip1=.96/27, $ip2=.0/27, and $ip3=.64/27.1597 1598 my (@together, @combinelist);1599 my $i=0;1600 while (my @data = $sth->fetchrow_array) {1601 my $testIP = new NetAddr::IP $data[0];1602 @together = $testIP->compact($cidr);1603 my $num = @together;1604 if ($num == 1) {1605 $cidr = $together[0];1606 $combinelist[$i++] = $testIP;1607 }1608 }1609 1610 # Clear old freeblocks entries - if any. $i==0 if not.1611 if ($i>0) {1612 $sth = $ip_dbh->prepare("delete from freeblocks where cidr=?");1613 foreach my $block (@combinelist) {1614 $sth->execute("$block");1615 }1616 }1617 1618 # insert "new" freeblocks entry1619 if ($webvar{alloctype} eq 'rr') {1620 $sth = $ip_dbh->prepare("insert into freeblocks values ('$cidr',".$cidr->masklen.1621 ",'<NULL>','n')");1622 } else {1623 $sth = $ip_dbh->prepare("insert into freeblocks values ('$cidr',".$cidr->masklen.1624 ",(select city from routed where cidr >>= '$cidr'),'y')");1625 }1626 $sth->execute;1627 1628 ##TEMP1629 }1630 ##TEMP1631 1632 # If we got here, we've succeeded. Whew!1633 $ip_dbh->commit;1634 }; # end eval1635 if ($@) {1636 carp "Transaction aborted because $@";1637 eval { $ip_dbh->rollback; };1638 syslog "err", "$authuser could not deallocate netblock '$webvar{block}': '$@'";1639 printAndExit("Could not deallocate netblock $webvar{block}: $@");1640 }1641 print "<div class=heading align=center>Success! $webvar{block} deleted.</div>\n";1642 1285 syslog "notice", "$authuser deallocated '$webvar{alloctype}'-type netblock $webvar{block}"; 1643 1644 } # end alloctype != netblock 1645 1646 printFooter; 1286 } else { 1287 if ($webvar{alloctype} =~ /^.i$/) { 1288 syslog "err", "$authuser could not deallocate static IP '$webvar{block}': '$msg'"; 1289 printError("Could not deallocate static IP $webvar{block}: $msg"); 1290 } else { 1291 syslog "err", "$authuser could not deallocate netblock '$webvar{block}': '$msg'"; 1292 printError("Could not deallocate netblock $webvar{block}: $msg"); 1293 } 1294 } 1295 1647 1296 } # finalDelete 1648 1297
Note:
See TracChangeset
for help on using the changeset viewer.